SPOJ COT3 - Combat on a tree

/*
考虑直接使用暴力来算的话 SG[i]表示以i为根的子树的SG值, 然后考虑枚举删除那个子树节点, 然后求拆成的树的sg异或值, 求mex即可 复杂度三次方 然后考虑尝试 整体来做 发现对于每次子树的合并, 每棵子树种的sg值相当是异或了其他的所有子树 而这个东西显然是可以用 线段树合并来维护的 最后找出所有sg不为0的点即可 */
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<cmath>
#define ll long long
#define M 100010
#define mmp make_pair
using namespace std;
int read() {
int nm = 0, f = 1;
char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
return nm * f;
}
int cor[M], cov[M * 60], laz[M * 60], ls[M * 60], rs[M * 60], rt[M], n, sg[M], cnt, ans[M], tot;
vector<int> to[M]; void add(int &now, int v, int deep) {
if(deep <= -1) return;
if(v & (1 << deep)) swap(ls[now], rs[now]);
laz[now] ^= v;
} void pushdown(int now, int deep) {
if(!laz[now] || !now) return;
add(ls[now], laz[now], deep - 1);
add(rs[now], laz[now], deep - 1);
laz[now] = 0;
} int merge(int now, int last, int deep) {
if(!now || !last) return now | last;
if(deep == -1) {
cov[now] |= cov[last];
return now;
}
pushdown(now, deep), pushdown(last, deep);
ls[now] = merge(ls[now], ls[last], deep - 1);
rs[now] = merge(rs[now], rs[last], deep - 1);
cov[now] = cov[ls[now]] && cov[rs[now]];
return now;
} void insert(int &now, int v, int deep) {
if(!now) now = ++cnt;
if(deep == -1) {
cov[now] = 1;
return;
}
if(v & (1 << deep)) insert(rs[now], v, deep - 1);
else insert(ls[now], v, deep - 1);
} int mex(int now, int deep) {
if(!now || deep == -1) return 0;
pushdown(now, deep);
if(!cov[ls[now]]) return mex(ls[now], deep - 1);
else return (1 << deep) + mex(rs[now], deep - 1);
} void dfs(int now, int fa) {
int tmp = 0;
for(int i = 0; i < to[now].size(); i++) {
int vj = to[now][i];
if(vj == fa) continue;
dfs(vj, now);
tmp ^= sg[vj];
}
if(!cor[now]) insert(rt[now], tmp, 17);
for(int i = 0; i < to[now].size(); i++) {
int vj = to[now][i];
if(vj == fa) continue;
add(rt[vj], tmp ^ sg[vj], 17);
rt[now] = merge(rt[now], rt[vj], 17);
}
sg[now] = mex(rt[now], 17);
} void get(int now, int fa, int anss) {
for(int i = 0; i < to[now].size(); i++) {
int vj = to[now][i];
if(vj == fa) continue;
anss ^= sg[vj];
}
if(anss == 0 && !cor[now]) ans[++tot] = now;
for(int i = 0; i < to[now].size(); i++) {
int vj = to[now][i];
if(vj == fa) continue;
get(vj, now, anss ^ sg[vj]);
}
} int main() {
n = read();
for(int i = 1; i <= n; i++) cor[i] = read();
for(int i = 1; i < n; i++) {
int vi = read(), vj = read();
to[vi].push_back(vj);
to[vj].push_back(vi);
}
dfs(1, 0);
get(1, 0, 0);
if(tot) {
sort(ans + 1, ans + tot + 1);
for(int i = 1; i <= tot; i++) cout << ans[i] << '\n';
} else puts("-1");
return 0;
}
上一篇:前端开发必备之Chrome开发者工具(下篇)


下一篇:一副美丽而庞大的SQL TUNING计划美图