T1 bzoj 4730 Alice和Bob又在玩游戏

题目大意:

Alice和Bob在玩游戏 n个节点,m条边(0<=m<=n-1),构成若干棵有根树,每棵树的根节点是该连通块内编号最小的点

Alice和Bob轮流操作,每回合选择一个没有被删除的节点x,将x及其所有祖先全部删除,不能操作的人输

思路:

根据博弈论的一些定理可以得到一个优秀的$n^2$做法

由$SG$定理得 每个点的$SG$函数值为$mex${子树内一个点的SG xor 该根节点其余儿子的SG}

因此对于每个点我们可以开一个trie树表示这个点的SG集合

合并的时候每个子树的$trie$树$xor$其余子树的$xor$和 然后像线段树合并一样合并$trie$树即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<cstring>
 7 #include<vector>
 8 #include<queue>
 9 #include<map>
10 #define rep(i,s,t) for(register int i=(s);i<=(t);++i)
11 #define dwn(i,s,t) for(register int i=(s);i>=(t);--i)
12 #define ren for(register int i=fst[x];i;i=nxt[i])
13 #define Fill(x,t) memset(x,t,sizeof(x))
14 #define ll long long
15 #define inf 2139062143
16 #define MAXN 200100
17 using namespace std;
18 inline int read()
19 {
20     int x=0,f=1;char ch=getchar();
21     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
22     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
23     return x*f;
24 }
25 int n,m,fst[MAXN],to[MAXN<<1],nxt[MAXN<<1],cnt,vis[MAXN],sg[MAXN];
26 int ls[MAXN*20],rs[MAXN*20],tag[MAXN*20],tot,ans,sz[MAXN*20],rt[MAXN*20];
27 const int maxDep=16;
28 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
29 void pshd(int k,int Dep)
30 {
31     if((tag[k]>>Dep)&1) swap(ls[k],rs[k]);
32     tag[k]&=((1<<Dep)-1);
33     tag[ls[k]]^=tag[k],tag[rs[k]]^=tag[k],tag[k]=0;
34 }
35 int merge(int x,int y,int Dep)
36 {
37     if(!(x*y)) return x|y;
38     pshd(x,Dep);pshd(y,Dep);
39     ls[x]=merge(ls[x],ls[y],Dep-1),rs[x]=merge(rs[x],rs[y],Dep-1);
40     return x;
41 }
42 void ins(int &x,int val,int Dep)
43 {
44     if(!x) x=++tot,sz[x]=1,ls[x]=rs[x]=tag[x]=0;if(!(~Dep)) return ;
45     pshd(x,Dep);ins((val&(1<<Dep))?rs[x]:ls[x],val,Dep-1);
46     sz[x]=sz[ls[x]]+sz[rs[x]];
47 }
48 int mex(int x,int res=0)
49 {
50     dwn(i,maxDep,0)
51     {
52         if(sz[ls[x]]<(1<<i)) x=ls[x];
53         else res|=(1<<i),x=rs[x];
54     }
55     return res;
56 }
57 void dfs(int x,int fa)
58 {
59     int sum=0;vis[x]=1;
60     ren if(to[i]!=fa) {dfs(to[i],x);sum^=sg[to[i]];}
61     ren if(to[i]!=fa) {tag[rt[to[i]]]^=(sum^sg[to[i]]);rt[x]=merge(rt[x],rt[to[i]],maxDep);}
62     ins(rt[x],sum,maxDep);sg[x]=mex(rt[x]);
63 }
64 int main()
65 {
66     int T=read();
67     while(T--)
68     {
69         n=read(),m=read(),tot=cnt=ans=0;int a,b;
70         while(m--) {a=read(),b=read();add(a,b);add(b,a);}
71         rep(i,1,n) if(!vis[i]) {dfs(i,0);ans^=sg[i];}
72         puts(ans?"Alice":"Bob");
73         rep(i,1,n) fst[i]=vis[i]=sg[i]=rt[i]=0;
74     }
75 }
View Code

相关文章:

  • 2021-12-15
  • 2021-06-15
  • 2021-04-02
  • 2021-08-12
  • 2021-12-25
  • 2021-05-27
  • 2021-09-06
  • 2022-01-20
猜你喜欢
  • 2022-01-27
  • 2021-08-19
  • 2022-12-23
  • 2021-04-18
  • 2021-07-06
  • 2021-12-28
相关资源
相似解决方案