版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ZscDst/article/details/88848746
A. Roman and Browser
n个数只有(1/-1),你可以选择一个位置b,然后把所有c位置的数删除, c=b+i*k ( i 可以为任意整数),求的最大值
思路
直接暴力枚举b然后搞一遍就OK
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int n, k, a[MAXN];
int main()
{
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
int ans = 0;
for (int b = 1; b <= k; b++)
{
int x1 = 0, x2 = 0;
for (int i = 1; i <= n; i++)
{
if ((i - b) % k == 0) continue;
if (a[i] == 1) x1++;
else x2++;
}
ans = max(ans, abs(x1 - x2));
}
printf("%d\n", ans);
return 0;
}
/*
4 2
1 1 -1 1
*/
B. Build a Contest
n个数范围为1~k的数字,问到当前位置是否能够凑齐1~k(凑齐一套以后把每个数的个数减一),可以该位为1,否则为0。
思路
set存是否够k个,cnt数组维护每个数字的个数,扫一遍就OK。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int n, m, a[MAXN], cnt[MAXN];
set<int> s;
int main()
{
scanf("%d%d", &m, &n);
string ans;
int t = 0;
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
s.insert(a[i]);
cnt[a[i]]++;
if (s.size() == m)
{
for (int j = 1; j <= m; j++)
{
cnt[j]--;
if (cnt[j] == 0) s.erase(j);
}
ans += '1';
}
else ans += '0';
}
cout << ans << endl;
return 0;
}
/*
3 11
2 3 1 2 2 2 3 2 2 3 1
*/
C. NN and the Optical Illusion
一个如图片中的图形,给你内圆半径和外圆个数,求外圆半径
思路
设大圆半径为x可得,解x即可。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
const double PI = acos(-1);
int n, r;
int main()
{
scanf("%d%d", &n, &r);
double s = sin(PI / n);
double x = s * r / (1 - s);
printf("%.7f", x);
return 0;
}
/*
3 1
*/
D. Dasha and Chess
交互题,999*999的网格,最多有667个黑车(走直线),你操控白王(可以攻击相邻的八个格子),让你在2000步攻击到一个黑子。
思路
花费500步把王移动到中间,然后以你画一个竖线和横线,四个区域散落着一些车,且一定有一个区域上的车小于167(667/4)个,我们朝着这个区域的反方向的对角线去走,一定可以。注意有些点有黑子不能去走。
#include<bits/stdc++.h>
using namespace std;
#define X first
#define Y second
const int MAXN = 1e3 + 5;
int x, y, cnt[MAXN];
pair<int, int> a[MAXN];
bool vis[MAXN][MAXN];
void Move(int ex, int ey)
{
while (x != ex || y != ey)
{
if (x < ex && vis[x + 1][y] == 0) x++;
else if (x > ex && vis[x - 1][y] == 0) x--;
if (y < ey && vis[x][y + 1] == 0) y++;
else if (y > ey && vis[x][y - 1] == 0) y--;
printf("%d %d\n", x, y);
fflush(stdout);
int k, xx, yy; scanf("%d%d%d", &k, &xx, &yy);
if (k == -1) break;
vis[a[k].X][a[k].Y] = 0;
a[k] = make_pair(xx, yy);
vis[a[k].X][a[k].Y] = 1;
}
}
int main()
{
scanf("%d%d", &x, &y);
for (int i = 1; i <= 666; i++)
{
scanf("%d%d", &a[i].X, &a[i].Y);
vis[a[i].X][a[i].Y] = 1;
}
Move(500, 500);
for (int i = 1; i <= 999; i++)
{
for (int j = 1; j <= 999; j++)
{
if (!vis[i][j]) continue;
if (i < x && j < y) cnt[0]++;
if (i < x && j > y) cnt[1]++;
if (i > x && j < y) cnt[2]++;
if (i > x && j > y) cnt[3]++;
}
}
if (cnt[0] <= 166) Move(999, 999);
else if (cnt[1] <= 166) Move(999, 1);
else if (cnt[2] <= 166) Move(1, 999);
else Move(1, 1);
return 0;
}
E. Andrew and Taxi
给定一个n个点m条边的有向图,现在需要通过反转一些边(花费为边权)的方向使得图中无环,最小化最大花费,输出这个花费和反转了哪些边
思路
最小化最大花费,显然想到二分。二分枚举这个值,然后拓扑排序判断边权比这个值大的边形成的图中是否存在环,如果还有环证明我们要增大这个值,否则减小这个值。
最后,比这个边小的那些边中哪些边需要反转呢,显然是u的拓扑序大于v的那些边。
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
//
struct Edge
{
int from, to, w;
Edge() {}
Edge(int from, int to, int w) : from(from), to(to), w(w) {}
};
struct Toposort
{
int n, m, t, c[MAXN], topo[MAXN];
vector<Edge> edges;
vector<int> G[MAXN];
int limit;
void init(int n)
{
this->n = n, m = 0;
edges.clear();
for (int i = 0; i <= n; i++) G[i].clear();
}
void AddEdge(int from, int to, int w)
{
edges.push_back(Edge(from, to, w));
m = edges.size();
G[from].push_back(m - 1);
}
bool dfs(int u)
{
c[u] = -1;//访问标志
for (auto& i : G[u])
{
Edge& e = edges[i];
if (e.w <= limit) continue;
if (c[e.to] < 0) return false;//存在有向环,失败退出
else if (!c[e.to] && !dfs(e.to)) return false;
}
c[u] = 1; topo[t--] = u;
return true;
}
bool toposort(int limit)
{
this->limit = limit;
t = n;
memset(c, 0, sizeof(c));
for (int u = 1; u <= n; u++)
{
if (c[u]) continue;
if (!dfs(u)) return false;
}
return true;
}
}gao;
int n, m, pos[MAXN];
bool check(int x)
{
return gao.toposort(x);
}
int main()
{
scanf("%d%d", &n, &m);
gao.init(n);
while (m--)
{
int u, v, w; scanf("%d%d%d", &u, &v, &w);
gao.AddEdge(u, v, w);
}
int L = 0, R = (int)1e9 + 1;
while (L < R)
{
int M = L + (R - L) / 2;
if (check(M)) R = M;
else L = M + 1;
}
check(L);
for (int i = 1; i <= n; i++) pos[gao.topo[i]] = i;
vector<int> ans;
for (int i = 0; i < gao.edges.size(); i++)
{
auto& e = gao.edges[i];
if (e.w <= L && pos[e.from] >= pos[e.to]) ans.push_back(i);
}
printf("%d %d\n", L, ans.size());
for (auto& i: ans) printf("%d ", i + 1);
return 0;
}
/*
5 6
2 1 1
5 2 6
2 3 2
3 4 3
4 5 5
1 5 4
*/
F. Ivan and Burgers
一个长度为n的数组c,Q次询问,每次询问[L,R]区间中xor和的最大值是多少?
思路
离线+线性基,以右端点为关键字排序,每次插入[1,R]区间的数,记录每个基最右面的位置,维护线性基。每个询问的最大值用大于L的基去构造即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 5e5 + 5;
struct LineBase
{
LL a[61], b[61];
int cnt;
int idx[61];
LineBase ()
{
cnt = 0;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
}
bool insert (LL v, int pos)
{
for (int i = 60; i >= 0; i--)
{
if (v & (1LL<<i))
{
if (!a[i]) { a[i] = v; idx[i] = pos; break; }
if (idx[i] < pos) swap(idx[i], pos), swap(a[i], v);
v ^= a[i];
}
}
return v > 0;
}
LL MAX(int l)
{
LL res = 0;
for (int i = 60; i >= 0; i--)
if ((res^a[i]) > res && idx[i] >= l) res ^= a[i];
return res;
}
LL MIN()
{
for (int i = 60; i >= 0; i--)
if (a[i]) return a[i];
return 0;
}
void rbuild()
{
for (int i = 60; i >= 0; i--)
{
for (int j = i - 1; j >= 0; j--)
{
if (a[i] & (1LL<<j)) a[i] ^= a[j];
}
}
for (int i = 0; i <= 60; i++)
if (a[i]) b[cnt++] = a[i];
}
LL kth(LL k) // k小值
{
LL res = 0;
if (k >= (1LL << cnt)) return -1;
for (int i = 60; i >= 0; i--)
if (k & (1LL << i)) res ^= b[i];
return res;
}
}LB;
struct Query
{
int l, r, id;
Query () {}
Query (int l, int r, int id) : l(l), r(r), id(id) {}
bool operator < (const Query& rhs) const
{
if (r != rhs.r) return r < rhs.r;
return l < rhs.l;
}
};
int n, q, c[MAXN];
LL ans[MAXN];
Query Q[MAXN];
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &c[i]);
scanf("%d", &q);
for (int i = 0; i < q; i++)
{
int l, r; scanf("%d%d", &l, &r);
l--, r--;
Q[i] = Query(l, r, i);
}
sort(Q, Q + q);
int r = 0;
for (int i = 0; i < q; i++)
{
while (r <= Q[i].r) LB.insert(c[r], r), r++;
ans[Q[i].id] = LB.MAX(Q[i].l);
}
for (int i = 0; i < q; i++) printf("%lld\n", ans[i]);
return 0;
}
/*
4
7 2 3 4
3
1 4
2 3
1 3
*/