SPOJ11414 COT3 博弈论 + Trie树合并

考虑对于每个子树从下往上依次考虑
对于叶子节点而言,如果可以染色,那么其\(sg\)值为\(1\),否则为\(0\)
考虑往上合并
如果选择了\(x\),那么后继状态就是其所有子树

如果选了其他子树中的一点,那么后继状态的构成如图所示

也就是,到当前根为止的所有其他子树的\(sg\)值异或上本身
那么,我们可以考虑维护一个数据结构,每次往上的时候,对于一棵子树内的点,异或上其他子树的\(sg\)值
至于查\(sg\)值,可以用一个支持查\(mex\)的东西
还需要合并
\(Trie\)树是一个不错的选择
输出答案就随意\(dfs\)一下,思路和上面的差不多
复杂度\(O(n \log n)\)
#include <map>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --)
const int sid = 2e5 + 5;
const int cid = 2e7 + 5;
#define gc getchar
inline int read() {
int p = 0, w = 1; char c = gc();
while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
return p * w;
}
bool cov[cid];
int n, id, tot, cnp;
int q[sid], sg[sid], ls[cid], rs[cid], xr[cid];
int rt[sid], col[sid], cap[sid], nxt[sid], node[sid];
inline void addedge(int u, int v) {
nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v;
}
inline void put_xor(int &o, int val, int dep) {
if(dep <= -1) return;
if(val & (1 << dep)) swap(ls[o], rs[o]);
xr[o] ^= val;
}
inline void pushdown(int o, int dep) {
if(!xr[o] || !o) return;
put_xor(ls[o], xr[o], dep - 1);
put_xor(rs[o], xr[o], dep - 1);
xr[o] = 0;
}
inline void insert(int &o, int val, int dep) {
if(!o) o = ++ id;
if(dep == -1) { cov[o] = 1; return; }
if(val & (1 << dep)) insert(rs[o], val, dep - 1);
else insert(ls[o], val, dep - 1);
}
inline int merge(int x, int y, int dep) {
if(!x || !y) return x + y;
if(dep == -1) { cov[x] |= cov[y]; return x; }
pushdown(x, dep); pushdown(y, dep);
ls[x] = merge(ls[x], ls[y], dep - 1);
rs[x] = merge(rs[x], rs[y], dep - 1);
cov[x] = cov[ls[x]] && cov[rs[x]];
return x;
}
inline int mex(int o, int dep) {
if(!o || dep == -1) return 0;
pushdown(o, dep);
if(!cov[ls[o]]) return mex(ls[o], dep - 1);
else return (1 << dep) + mex(rs[o], dep - 1);
}
#define cur node[i]
inline void dfs(int o, int fa) {
int nsg = 0;
for(int i = cap[o]; i; i = nxt[i])
if(cur != fa) dfs(cur, o), nsg ^= sg[cur];
if(!col[o]) insert(rt[o], nsg, 17);
for(int i = cap[o]; i; i = nxt[i])
if(cur != fa) {
put_xor(rt[cur], nsg ^ sg[cur], 17);
rt[o] = merge(rt[o], rt[cur], 17);
}
sg[o] = mex(rt[o], 17);
}
inline void find(int o, int fa, int SG) {
for(int i = cap[o]; i; i = nxt[i])
if(cur != fa) SG ^= sg[cur];
if(SG == 0 && !col[o]) q[++ tot] = o;
for(int i = cap[o]; i; i = nxt[i])
if(cur != fa) find(cur, o, SG ^ sg[cur]);
}
int main() {
n = read();
rep(i, 1, n) col[i] = read();
rep(i, 2, n) {
int u = read(), v = read();
addedge(u, v); addedge(v, u);
}
dfs(1, 0);
find(1, 0, 0);
if(tot) {
sort(q + 1, q + tot + 1);
rep(i, 1, tot) printf("%d\n", q[i]);
}
else puts("-1");
return 0;
}
SPOJ11414 COT3 博弈论 + Trie树合并的更多相关文章
- Codeforces Round #333 (Div. 1) D. Acyclic Organic Compounds trie树合并
D. Acyclic Organic Compounds You are given a tree T with n vertices (numbered 1 through n) and a l ...
- CF888G Xor-MST 生成树、分治、Trie树合并
传送门 第一次接触到Boruvka求最小生成树 它的原版本是:初始每一个点构成一个连通块,每一次找到每一个连通块到其他的连通块权值最短的边,然后合并这两个连通块.因为每一次连通块个数至少减半,所以复杂 ...
- 2017ACM/ICPC广西邀请赛 K- Query on A Tree trie树合并
Query on A Tree Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Othe ...
- [杂题]:staGame(博弈论+Trie树+DFS)
题目描述 $pure$和$dirty$决定玩$T$局游戏.对于每一局游戏,有$n$个字符串,并且每一局游戏由$K$轮组成.具体规则如下:在每一轮游戏中,最开始有一个空串,两者轮流向串的末尾添加一个字符 ...
- Trie 树进阶学习笔记
前言 没脑子选手发现自己什么都不会 ... \(\text{More and more vegetables, What should I do?}\) 正文 Trie 树简介 大概是人类的话都知道吧 ...
- 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\)个点的树,每个点是黑色或白色.两个人轮流操作,每次可以选一个白色的点,将它到根节点路径上的所有点染黑.不能操作的人输,求先手是否能赢.如果能 ...
- LOJ 2991 「THUSC 2016」补退选——trie+线段树合并或vector
题目:https://loj.ac/problem/2291 想了线段树合并的做法.就是用线段树维护 trie 的每个点在各种时间的操作. 然后线段树合并一番,线段树维护前缀最大值,就是维护最大子段和 ...
- CodeForces - 778C: Peterson Polyglot (启发式合并trie树)
Peterson loves to learn new languages, but his favorite hobby is making new ones. Language is a set ...
随机推荐
- P2868 [USACO07DEC]观光奶牛Sightseeing Cows
P2868 [USACO07DEC]观光奶牛Sightseeing Cows [](https://www.cnblogs.com/images/cnblogs_com/Tony-Double-Sky ...
- Java基础-线程安全问题汇总
Java基础-线程安全问题汇总 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.内存泄漏和内存溢出(out of memory)的区别 1>.什么是内存溢出 答:内存溢出指 ...
- SQL记录-PLSQL游标
PL/SQL游标 Oracle会创建一个存储区域,被称为上下文区域,用于处理SQL语句,其中包含需要处理的语句,例如所有的信息,行数处理,等等. 游标是指向这一上下文的区域. PL/SQL通过控制光标 ...
- [转载]为什么有些MP4文件在Chrome浏览器上播放不了?
http://blog.sina.com.cn/s/blog_6bb7ebcc0101c2ja.html Chrome浏览器支持HTML5,它支持原生播放部分的MP4格式(不用通过Flash等插件). ...
- Spring Mvc + Maven + yuicompressor 使用 profile 来压缩 javascript ,css 文件; (十)
profile相关知识点: 在开发项目时,设想有以下场景: 你的Maven项目存放在一个远程代码库中(比如github),该项目需要访问数据库,你有两台电脑,一台是Linux,一台是Mac OS X, ...
- HDU 4608 I-number 2013 Multi-University Training Contest 1 1009题
题目大意:输入一个数x,求一个对应的y,这个y满足以下条件,第一,y>x,第二,y 的各位数之和能被10整除,第三,求满足前两个条件的最小的y. 解题报告:一个模拟题,比赛的时候确没过,感觉这题 ...
- VIM 配置随手记
刚开始使用VIM, 主要想用它来写python. 目标是颜色比较舒适, 并且能够自动换行自动补全. .vimrc 设置 这是类似 .bashrc 的配置文件, vim 的各种配置都可以在里面实现. 一 ...
- Paint Fence
There is a fence with n posts, each post can be painted with one of the k colors.You have to paint a ...
- umount /mnt/cdrom
这是因为有程序正在访问这个设备,最简单的办法就是让访问该设备的程序退出以后再umount.可能有时候用户搞不清除究竟是什么程序在访问设备,如果用户不急着umount,则可以用: umount -l / ...
- MAC系统下Sublime Text3 配置Python3详细教程
MAC系统下Sublime Text3 配置Python3详细教程(亲测有效) https://blog.csdn.net/weixin_41768008/article/details/798590 ...