博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UOJ#266. 【清华集训2016】Alice和Bob又在玩游戏 博弈,DSU on Tree,Trie
阅读量:5319 次
发布时间:2019-06-14

本文共 2693 字,大约阅读时间需要 8 分钟。

原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ266.html

题解

首先我们可以直接暴力 $O(n^2)$ 用 sg 函数来算答案。

对于一个树就是枚举一下从根出发到哪一个节点为止的路径被删掉了,剩下所有的子树的sg值xor起来,对于每一个路径后的答案取一个 mex 。

我们考虑快速的做这个过程。

直接写个 Trie 再 DSU on tree 就好了,只要支持查询 mex 和整棵 trie 对某一个值 xor 这两种操作就好了。

时间复杂度 $O(n\log ^2n)$ 。

代码

#pragma GCC optimize("Ofast","inline")#include 
#define clr(x) memset(x,0,sizeof (x))#define For(i,a,b) for (int i=a;i<=b;i++)#define Fod(i,b,a) for (int i=b;i>=a;i--)#define pb push_back#define mp make_pair#define fi first#define se second#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')#define outval(x) printf(#x" = %d\n",x)#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")#define outtag(x) puts("----------"#x"----------")#define outarr(a,L,R) printf(#a"[%d...%d] = ",L,R);\ For(_v2,L,R)printf("%d ",a[_v2]);puts("");using namespace std;typedef long long LL;LL read(){ LL x=0,f=0; char ch=getchar(); while (!isdigit(ch)) f|=ch=='-',ch=getchar(); while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return f?-x:x;}const int N=100005;namespace Trie{ const int S=N*20*20; int son[S][2],size[S],c=0; #define ls son[x][0] #define rs son[x][1] void Init(){ while (c) clr(son[c]),size[c]=0,c--; } void Ins(int &x,int d,int v,int tag){ if (!x) x=++c,size[x]=1; if (d<0) return; Ins(son[x][(v^tag)>>d&1],d-1,v,tag); size[x]=size[ls]+size[rs]; } void Get(int x,int d,int v,int tag,vector
&vec){ if (!x) return; if (d<0) return vec.pb(v); Get(son[x][tag>>d&1],d-1,v,tag,vec); Get(son[x][~tag>>d&1],d-1,v|(1<
>d&1]]<(1<
>d&1],d-1,v,tag); else return Ask(son[x][~tag>>d&1],d-1,v|(1<
e[N];struct trie{ int rt,tag;}t[N];int cnt;int size[N],son[N],sg[N],id[N];void dfs(int x,int pre){ size[x]=1,son[x]=0; for (auto y : e[x]) if (y!=pre){ dfs(y,x); size[x]+=size[y]; if (!son[x]||size[son[x]]
gid;void dfs2(int x,int pre){ sg[x]=0; int s=0; for (auto y : e[x]) if (y!=pre){ dfs2(y,x); s^=sg[y]; } if (!son[x]) id[x]=++cnt,t[cnt].rt=t[cnt].tag=0; else t[id[x]=id[son[x]]].tag^=s^sg[son[x]]; trie &now=t[id[x]]; Trie::Ins(now.rt,17,s,now.tag); for (auto y : e[x]) if (y!=pre&&y!=son[x]){ gid.clear(); Trie::Get(t[id[y]].rt,17,0,t[id[y]].tag,gid); for (auto v : gid) Trie::Ins(now.rt,17,v^(s^sg[y]),now.tag); } sg[x]=Trie::Ask(now.rt,17,0,now.tag);}void Main(){ n=read(),m=read(); For(i,0,n) e[i].clear(),size[i]=0; For(i,1,m){ int x=read(),y=read(); e[x].pb(y),e[y].pb(x); } cnt=0; int ans=0; Trie::Init(); For(i,1,n) if (!size[i]){ dfs(i,0); dfs2(i,0); ans^=sg[i]; } puts(ans?"Alice":"Bob");}int main(){ int T=read(); while (T--) Main(); return 0;}

  

转载于:https://www.cnblogs.com/zhouzhendong/p/UOJ266.html

你可能感兴趣的文章