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\) 每 ...
随机推荐
- Kubernetes 知识点
自己总结的 Kubernetes 的各模块(待补充) 各模块包含关系: namespace => node => pod => container table th:first-of ...
- js 去掉前后空格(正则表达式方法)
代码: ' aaa '.replace(/(^\s*)|(\s*$)/g, '')
- git 常见命令 和 git 原理图
git 工作原理图:git 有4 个仓库 这是 git和 svn 一个巨大的区别,所以git 没网也能提交代码和查看记录. svn 只有2 个仓库 ,一个远程一个本地. 1 创建git 仓库( 参数 ...
- golang interface判断为空nil
要判断interface 空的问题,首先看下其底层实现. interface 底层结构 根据 interface 是否包含有 method,底层实现上用两种 struct 来表示:iface 和 ef ...
- C#:单元测试(VS2015)
根据VS2015的提示,仅支持在共有类或共有方法中支持创建单元测试.所以,如果我们要测试私有或是保护的类和方法,是要先将他们暂时设定成公有类型. 在VS2015中创建单元测试,只要在我们想测试的地方点 ...
- Centos7 设置Mongodb开机启动-自定义服务
(1).在/lib/systemd/system/目录下新建mongodb.service文件,内容如下 [Unit] Description=mongodb After=network.target ...
- SourceInsight宏插件1(非常好用,强力推荐)
对于一直使用sourceinsight编辑C/C++代码的工程师们,sourceinsight是一个非常好用的编辑工具可以任意定位,跳转,回退,本人一直使用该工具做C/C++开发,sourceinsi ...
- GTID的相关特性
配置MySQL GTID 主从复制 基于mysqldump搭建gtid主从 二.GTID如何跳过事务冲突 1 2 3 4 5 6 7 8 9 10 11 很多无法预料的情形导致mysql主从发生事务冲 ...
- Java第04次实验提纲(面向对象2-继承、多态、抽象类与接口)
PTA 题集面向对象2-进阶-多态接口内部类 第1次实验 1.1 题集5-1(Comparable) 难点:如果传入对象为null,或者传入对象的某个属性为null,怎么处理? 1.2 题集5-2(C ...
- PHP 中如何创建和修改数组?
PHP中使用array来创建一个数组:array( key=>value , key=>value …… )用方括号的语法来修改数组:$arr[] = value 例如:$arr = ar ...