QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#936608 | #10226. Tree Flip | thinking (Fedor Romashov, Alexey Mikhnenko, Gimran Abdullin)# | AC ✓ | 537ms | 20648kb | C++20 | 9.3kb | 2025-03-15 21:48:20 | 2025-03-15 21:48:21 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
#define all(a) begin(a), end(a)
#define len(a) int((a).size())
#ifdef LOCAL
#include "debug.h"
#else
#define dbg(...)
#define dprint(...)
#define debug if constexpr (false)
#endif // LOCAL
/*
* Node must have default constructor.
* Node must have static function merge.
* Node must have .push and .clear_after_push methods.
*/
template<typename node>
class segtree {
private:
void build(int v, int vl, int vr) {
if (vr - vl <= 1)
return;
int vm = (vl + vr) >> 1;
build(v << 1, vl, vm);
build(v << 1 | 1, vm, vr);
tree[v] = node::merge(tree[v << 1], tree[v << 1 | 1]);
}
template<typename T>
void build(int v, int vl, int vr, const std::vector<T> &arr) {
if (vl == vr)
return;
if (vr - vl == 1) {
tree[v] = node(arr[vl]);
return;
}
int vm = (vl + vr) >> 1;
build(v << 1, vl, vm, arr);
build(v << 1 | 1, vm, vr, arr);
tree[v] = node::merge(tree[v << 1], tree[v << 1 | 1]);
}
template<typename... Args>
void _update(int v, int vl, int vr, int l, int r, Args&&... args) {
if (r <= vl || vr <= l)
return;
if (l <= vl && vr <= r) {
tree[v].apply(std::forward<Args>(args)..., vl, vr);
return;
}
int vm = (vl + vr) >> 1;
tree[v].push(tree[v << 1], vl, vm);
tree[v].push(tree[v << 1 | 1], vm, vr);
tree[v].clear_after_push();
_update(v << 1, vl, vm, l, r, std::forward<Args>(args)...);
_update(v << 1 | 1, vm, vr, l, r, std::forward<Args>(args)...);
tree[v] = node::merge(tree[v << 1], tree[v << 1 | 1]);
}
node _query(int v, int vl, int vr, int l, int r) {
if (l <= vl && vr <= r)
return tree[v];
int vm = (vl + vr) >> 1;
tree[v].push(tree[v << 1], vl, vm);
tree[v].push(tree[v << 1 | 1], vm, vr);
tree[v].clear_after_push();
if (r <= vm)
return _query(v << 1, vl, vm, l, r);
if (vm <= l)
return _query(v << 1 | 1, vm, vr, l, r);
return node::merge(_query(v << 1, vl, vm, l, r), _query(v << 1 | 1, vm, vr, l, r));
}
template<typename T>
int _find_first(int v, int vl, int vr, int from, const T &checker) {
if (vr <= from)
return n;
if (from <= vl && !checker(tree[v], vl, vr))
return n;
if (vr - vl == 1)
return vl;
int vm = (vl + vr) >> 1;
tree[v].push(tree[v << 1], vl, vm);
tree[v].push(tree[v << 1 | 1], vm, vr);
tree[v].clear_after_push();
int res = _find_first(v << 1, vl, vm, from, checker);
return res == n ? _find_first(v << 1 | 1, vm, vr, from, checker) : res;
}
template<typename T>
int _find_last(int v, int vl, int vr, int from, const T &checker) {
if (from <= vl)
return -1;
if (vr <= from && !checker(tree[v], vl, vr))
return -1;
if (vr - vl == 1)
return vl;
int vm = (vl + vr) >> 1;
tree[v].push(tree[v << 1], vl, vm);
tree[v].push(tree[v << 1 | 1], vm, vr);
tree[v].clear_after_push();
int res = _find_last(v << 1 | 1, vm, vr, from, checker);
return res == -1 ? _find_last(v << 1, vl, vm, from, checker) : res;
}
public:
int n;
std::vector<node> tree;
segtree(int n) : n(n), tree(4 * n, node()) {
build(1, 0, n);
}
template<typename T>
segtree(const std::vector<T> &arr) : n(arr.size()), tree(4 * n) {
build(1, 0, n, arr);
}
int size() const {
return n;
}
template<typename... Args>
void update(int l, int r, Args&&... args) {
if (r <= l)
return;
_update(1, 0, n, l, r, std::forward<Args>(args)...);
}
node query(int l, int r) {
assert(std::max(0, l) < std::min(n, r)); // or return node() in this case
return _query(1, 0, n, l, r);
}
// Trying to find first true on the interval [from, n).
// Returns n if not found.
template<typename T>
int find_first(int from, const T &checker) {
return _find_first(1, 0, n, from, checker);
}
// Trying to find last true on the interval [0, from).
// Returns -1 if not found.
template<typename T>
int find_last(int from, const T &checker) {
return _find_last(1, 0, n, from, checker);
}
};
struct node2 {
array<int, 2> cnt;
int mod = 0;
node2(int x = 0) {
cnt.fill(0);
cnt[x] = 1;
}
void apply(int d, int /* vl */, int /* vr */) {
if (d) {
mod ^= d;
swap(cnt[0], cnt[1]);
}
}
void push(node2 &child, int /* cl */, int /* cr */) {
child.apply(mod, int(), int());
}
void clear_after_push() {
mod = 0;
}
static node2 merge(const node2 &left, const node2 &right) {
node2 res;
for (int i : {0, 1}) {
res.cnt[i] = left.cnt[i] + right.cnt[i];
}
return res;
}
};
struct node {
int val;
array<int, 2> cnt;
node(int x = 0) : val(x) {
cnt.fill(0);
}
void apply(int d, int /* vl */, int /* vr */) {
val ^= d;
swap(cnt[0], cnt[1]);
}
void apply(array<int, 2> d, int /* vl */, int /* vr */) {
cnt = d;
}
void push(node /*&child*/, int /* cl */, int /* cr */) {}
void clear_after_push() {}
static node merge(const node &left, const node &right) {
node res;
for (int i : {0, 1}) {
res.cnt[i] = left.cnt[i ^ right.val] + right.cnt[i];
}
res.val = left.val ^ right.val;
return res;
}
};
void solve() {
int n, q;
cin >> n >> q;
vector<int> a(n);
for (auto &x : a) {
cin >> x;
}
vector<vector<int>> g(n);
for (int i = 1; i < n; i++) {
int v, u;
cin >> v >> u;
v--, u--;
g[v].push_back(u);
g[u].push_back(v);
}
vector<int> sz(n, 1), par(n, -1);
[&](this auto dfs, int v) -> void {
for (auto u : g[v]) {
g[u].erase(find(all(g[u]), v));
par[u] = v;
dfs(u);
sz[v] += sz[u];
}
sort(all(g[v]), [&](int a, int b) {
return sz[a] > sz[b];
});
}(0);
int timer = 0;
vector<int> tin(n), tout(n), head(n);
[&](this auto dfs, int v, int h) -> void {
head[v] = h;
tin[v] = timer++;
for (int i = 0; i < len(g[v]); i++) {
int u = g[v][i];
dfs(u, (i == 0 ? h : u));
}
tout[v] = timer;
}(0, 0);
segtree<node> tree(n);
segtree<node2> tree2(n);
for (int i = 0; i < n; i++) {
if (a[i]) {
tree.update(tin[i], tin[i] + 1, 1);
tree2.update(tin[i], tout[i], a[i]);
}
}
auto pref_xor = [&](int v) {
return tree2.query(tin[v], tin[v] + 1).cnt[0] == 0;
};
auto get_cnt = [&](int v) {
auto cur = tree2.query(tin[v], tout[v]).cnt;
if (!g[v].empty()) {
int u = g[v][0];
auto cur2 = tree2.query(tin[u], tout[u]).cnt;
for (int i : {0, 1}) {
cur[i] -= cur2[i];
}
}
if (par[v] != -1 && pref_xor(par[v])) {
swap(cur[0], cur[1]);
}
return cur;
};
dbg(par);
dbg(head);
for (int i = 0; i < n; i++) {
dbg(i, get_cnt(i));
tree.update(tin[i], tin[i] + 1, get_cnt(i));
}
int root = 0;
while (q--) {
int t, x;
cin >> t >> x;
x--;
if (t == 1) {
a[x] ^= 1;
tree.update(tin[x], tin[x] + 1, 1);
tree2.update(tin[x], tout[x], 1);
for (int v = x; v != -1; v = par[head[v]]) {
tree.update(tin[v], tin[v] + 1, get_cnt(v));
}
} else {
root = x;
}
int root_pref = 0;
array<int, 2> prev{};
int ans = 0;
int v = root;
while (v != -1) {
auto cur = tree.query(tin[head[v]], tin[v] + 1);
for (int i : {0, 1}) {
cur.cnt[i] -= prev[i ^ a[v]];
}
ans += cur.cnt[root_pref ^ 1];
if (!g[v].empty()) {
auto left = tree2.query(tin[g[v][0]], tout[g[v][0]]).cnt;
if (pref_xor(v)) {
swap(left[0], left[1]);
}
ans += left[root_pref ^ 1 ^ a[v]];
}
root_pref ^= cur.val;
v = head[v];
prev = tree2.query(tin[v], tout[v]).cnt;
if (par[v] != -1 && pref_xor(par[v])) {
swap(prev[0], prev[1]);
}
v = par[v];
}
cout << ans << '\n';
}
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int t;
cin >> t;
while (t--) {
solve();
}
}
这程序好像有点Bug,我给组数据试试?
詳細信息
Test #1:
score: 100
Accepted
time: 0ms
memory: 3712kb
input:
1 3 3 0 0 1 1 2 3 1 1 1 2 2 1 1
output:
2 1 1
result:
ok 3 lines
Test #2:
score: 0
Accepted
time: 537ms
memory: 20648kb
input:
1 100000 100000 0 0 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 1 1 1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 0 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 1 0 0 0 0 1 0 0 0 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 1 0 1 1 0 1 0 1 1 0 0 1 1 1 1 1 1 1 1 1 0 1 0 0 1 0 0 1 0 1 0 0 1 1 1 0 1 1 1 1 0 1 1 ...
output:
49874 50073 49944 49944 49917 49916 49984 49947 49945 49870 50089 50088 50024 50025 49980 49862 49984 49982 49983 49990 49949 49951 49950 50195 50196 50196 49955 50072 50071 49993 50021 50134 49985 49917 49886 49885 50134 49818 49819 49952 49954 49955 49986 50046 50018 50021 50020 50017 50130 50132 ...
result:
ok 100000 lines
Test #3:
score: 0
Accepted
time: 287ms
memory: 5000kb
input:
10 9141 9858 1 1 1 0 0 1 1 1 0 0 1 1 0 1 1 1 0 1 0 0 1 0 0 0 1 1 0 1 1 0 0 1 1 0 0 1 0 1 1 1 0 1 1 0 1 1 1 0 0 0 1 1 1 0 1 0 1 1 1 0 0 1 1 1 0 1 1 1 1 0 1 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 1 1 1 1 0 1 0 0 0 0 1 1 1 0 1 0 1 1 1 0 1 1 1 1 1 1 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 1 1...
output:
4598 4606 4568 4553 4529 4529 4601 4600 4534 4546 4548 4621 4597 4515 4586 4586 4587 4536 4552 4553 4555 4556 4618 4580 4555 4561 4549 4547 4547 4517 4594 4593 4556 4556 4554 4554 4553 4557 4603 4603 4602 4602 4600 4516 4523 4593 4592 4589 4590 4591 4584 4543 4542 4532 4537 4562 4611 4558 4556 4591 ...
result:
ok 95405 lines
Test #4:
score: 0
Accepted
time: 211ms
memory: 6392kb
input:
10 9997 9996 1 1 1 0 0 0 1 1 0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 0 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 1 0 0 0 0 1 1 1 0 0 1 1 1 1 0 0 0 1 1 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 0 1 1 0 0 0 1 1 1 1 0 0 0 1 1 0 0 1 0 0 1 0 1 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 1 1 0 0 1 1 0 0 1 1 0 1 1 1 0 1 0 1 1 0 0 0 0 0 1 1 1 1 1 1...
output:
4997 5001 4990 5018 5024 5011 5042 5066 4955 4971 4971 4937 4947 4983 5050 4971 5038 5038 4960 5032 4966 4924 4999 4957 5041 5041 4957 4973 5000 5025 4998 5015 5016 5020 5006 5020 5015 5036 5008 5008 4975 4996 4957 4986 5051 4998 5004 4990 4990 4965 4995 4963 4987 5009 4989 5007 5007 4985 4998 5007 ...
result:
ok 99942 lines
Test #5:
score: 0
Accepted
time: 41ms
memory: 3712kb
input:
10000 10 10 0 1 0 1 1 0 0 0 0 1 3 5 5 10 5 4 2 10 2 7 9 4 2 1 3 8 6 7 2 5 1 7 1 5 2 1 1 7 1 9 2 1 2 7 1 8 2 4 4 10 1 1 0 1 1 4 1 2 2 3 1 4 1 4 2 4 1 3 2 3 2 3 1 2 2 2 2 1 2 4 10 10 0 1 0 1 1 1 0 0 1 0 10 7 7 3 10 5 10 1 1 8 5 6 10 9 2 9 4 3 2 1 2 6 1 1 2 7 1 7 1 5 1 3 1 5 2 7 1 3 4 10 0 1 1 1 1 2 3 ...
output:
7 5 5 3 5 4 4 3 4 7 2 1 3 2 2 2 3 2 2 2 3 3 5 5 5 5 5 5 5 5 2 2 2 2 2 1 3 2 1 1 1 2 2 2 2 2 1 1 1 2 4 5 4 3 5 5 3 4 5 4 4 5 2 3 2 4 5 4 2 3 2 2 2 2 2 2 2 3 3 3 5 2 2 7 2 2 3 2 7 6 4 3 1 1 2 2 3 4 5 4 6 6 4 5 6 4 5 6 6 7 5 2 4 2 4 1 3 2 4 4 3 7 2 6 6 7 6 1 1 1 0 0 1 1 2 1 2 1 2 2 4 2 1 1 2 2 4 3 3 2 ...
result:
ok 100000 lines
Extra Test:
score: 0
Extra Test Passed