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;
}
SPOJ COT3 - Combat on a tree的更多相关文章
- SPOJ COT3 Combat on a tree(Trie树、线段树的合并)
题目链接:http://www.spoj.com/problems/COT3/ Alice and Bob are playing a game on a tree of n nodes.Each n ...
- SPOJ COT3.Combat on a tree(博弈论 Trie合并)
题目链接 \(Description\) 给定一棵\(n\)个点的树,每个点是黑色或白色.两个人轮流操作,每次可以选一个白色的点,将它到根节点路径上的所有点染黑.不能操作的人输,求先手是否能赢.如果能 ...
- BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 5217 Solved: 1233 ...
- BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树
2588: Spoj 10628. Count on a tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/J ...
- Bzoj 2588: Spoj 10628. Count on a tree 主席树,离散化,可持久,倍增LCA
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2588 2588: Spoj 10628. Count on a tree Time Limit ...
- BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )
Orz..跑得还挺快的#10 自从会树链剖分后LCA就没写过倍增了... 这道题用可持久化线段树..点x的线段树表示ROOT到x的这条路径上的权值线段树 ----------------------- ...
- 【BZOJ2589】 Spoj 10707 Count on a tree II
BZOJ2589 Spoj 10707 Count on a tree II Solution 吐槽:这道题目简直...丧心病狂 如果没有强制在线不就是树上莫队入门题? 如果加了强制在线怎么做? 考虑 ...
- 【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA
[BZOJ2588]Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lasta ...
- 【SPOJ】QTREE7(Link-Cut Tree)
[SPOJ]QTREE7(Link-Cut Tree) 题面 洛谷 Vjudge 题解 和QTREE6的本质是一样的:维护同色联通块 那么,QTREE6同理,对于两种颜色分别维护一棵\(LCT\) 每 ...
随机推荐
- mongodb之 oplog 日志详解
1:oplog简介 oplog是local库下的一个固定集合,Secondary就是通过查看Primary 的oplog这个集合来进行复制的.每个节点都有oplog,记录这从主节点复制过来的信息,这样 ...
- git 常见命令 和 git 原理图
git 工作原理图:git 有4 个仓库 这是 git和 svn 一个巨大的区别,所以git 没网也能提交代码和查看记录. svn 只有2 个仓库 ,一个远程一个本地. 1 创建git 仓库( 参数 ...
- 用C语言解决python多线程中的GIL问题
在使用python多线程的时候为了解决GIL问题,有些代码得用C语言写,那么就得生成动态链接库. 当创建动态链接库时,独立位置信息(position independent)代码也需要生成.这可以帮助 ...
- leftJoin鏈錶查詢
//待使用券碼 $code_record_no = DB::table('fook_platform_order as a') ->select('o.code','o.apportion_bi ...
- Jmeter使用流程及简单分析监控
本文摘自:一颗糖果 https://www.cnblogs.com/linglingyuese/archive/2013/03/04/linglingyuese-one.html 1.下载Jmet ...
- Linux Centos配置ssh客户端工具putty
配置ssh客户端工具putty 1.直接点击putty.exe文件 2.配置putty 3.配置putty编码 4.配置putty字体大小 5.配置putty样式 6.保存配置信息 7.配置MTp ...
- mysql、MS SQL关于分页的sql查询语句 limit 和row_number() OVER函数
在做项目的时候需要些分页,用的数据库是MySQL,之前看到的参考例子是用MS SQL做的,在MS SQL.Oracle里面有ROW_NUMBER() OVER函数可以在数据库里对数据进行分组.百度后的 ...
- PHP 中 call_user_func 函数 和 call_user_func_array 函数的区别
PHP 中 call_user_func() 函数 和 call_user_func_array() 函数都是回调函数,在写接口的时候经常会用到,但是他们有什么区别呢? 它们的第一个参数都是被调用的回 ...
- 解决“chrome adobe flash player不是最新版本”的方法
chrome地址栏输入chrome://components 更新flash后,重启chrome即可,可能需要搭梯子才能更新.
- html多个水平并列组件自适应等高的做法
做一个div盒子,设置over-flow:hidden,设置高度为auto.然后再盒子里排列若干inline-block,inline元素. 自适应的话常用做法是用line-height,font-s ...