Codeforces Global Round 13
Codeforces Global Round 13
A - K-th Largest Value
int a[N];
int main() {
IOS; cin >> n >> m;
rep (i, 1, n) cin >> a[i], k += a[i];
rep (i, 1, m) {
int op, x; cin >> op >> x;
if (op == 1) {
a[x] ^= 1;
if (a[x]) ++k;
else --k;
} else {
cout << (k >= x ? 1 : 0) << '\n';
}
}
return 0;
}
## B - Minimal Cost
```c++
int main() {
IOS;
for (cin >> _; _; --_) {
ll u, v, ans = 2e9; cin >> n >> u >> v;
rep (i, 1, n) cin >> a[i];
rep (i, 2, n) {
if (a[i] == a[i - 1]) umin(ans, v + min(u, v));
else if (abs(a[i] - a[i - 1]) == 1) umin(ans, min(u, v));
else ans = 0;
}
cout << ans << '\n';
}
return 0;
}
C - Pekora and Trampoline
差分, 可以用树状优化, 没必要
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n; ll ans = 0;
rep (i, 1, n) cin >> a[i], b[i] = 0;
rep (i, 1, n) {
ans += max(a[i] - 1 - b[i], 0);
rep (j, i + 2, min(i + a[i], n)) ++b[j];
b[i + 1] += max(b[i] - a[i] + 1, 0);
}
cout << ans << "\n";
}
return 0;
}
D - Zookeeper and The Infinite Zoo
每次都可以将 u 的二进制上的1向左移或将相邻的1替换成1个1, 第0位补0, 即我们可以将 u 末尾的1 任意左移或消去
当从二进制末尾到高位, 任意位置 u 包含 1 的个数 >= v 包含 1 的个数, 即可到达 v
int main() {
IOS;
for (cin >> _; _; --_) {
ll u, v; cin >> u >> v; bool f = 0;
memset(a, 0, sizeof a); memset(b, 0, sizeof b);
if (u > v) f = 1;
for (n = 0; u; a[++n] = (u & 1), u >>= 1);
for (m = 0; v; b[++m] = (v & 1), v >>= 1);
int sa = 0, sb = 0;
rep (i, 1, m) {
sa += a[i]; sb += b[i];
if (sa < sb) f = 1;
}
cout << (!f ? "YES\n" : "NO\n");
}
return 0;
}
E. Fib-tree
二分 + dfs
本质是个二分题, 每次将一棵树尝试分成两颗Fbi树 直到当前这棵树只有一个节点
关键是怎么二分的问题, 二分一棵树, 就是找这棵树的一条边把这颗树分成两部分, 递归 判断这两棵子树是不是Fbi树
然后就是怎么枚举边, 这个就很巧了, 通过dfs枚举当前这棵树的边, 本来dfs就是枚举边和点的, 一边枚举, 一边二分树
注意到一棵树分成两棵Fbi树, 最多有两种分法 \(fbi[i] = fbi[i - 1] + fbi[i - 2] = fbi[i - 2] * 2 + fbi[i - 3]\)
即可找到两棵子孙, 其节点数量为fbi[i - 2]
层数 * 当前子树的边数 * set维护断开了哪些边 即 期望为 \(O(2^{logn} * logn * logn) = O(nlog^2n)\)
int n, m, _, k, cas;
int sz[50][N];
bool st[N];
set<pair<int, int>> v;
VI h[N];
bool work(int x, int fa, int sum, int d) {
sz[d][x] = 1;
if (!st[sum]) return 0;
if (sum == 1) return 1;
for (auto& y : h[x]) if (y != fa && !v.count({ min(x, y), max(x, y) })) {
if (work(y, x, sum, d)) return 1;
sz[d][x] += sz[d][y];
}
if (!st[sz[d][x]] || !st[sum - sz[d][x]]) return 0;
v.insert({ min(x, fa), max(x, fa) });
if (work(x, 0, sz[d][x], d + 1) && work(fa, 0, sum - sz[d][x], d + 1)) return 1;
v.erase({ min(x, fa), max(x, fa) }); return 0;
}
int main() {
IOS; cin >> n;
for (int i = 0, j = 1; j <= n; st[j] = 1, swap(i += j, j));
rep (i, 2, n) {
int u, v; cin >> u >> v;
h[u].pb(v); h[v].pb(u);
}
cout << (work(1, 0, n, 0) ? "YES" : "NO");
return 0;
}