UOJ 266 清华集训2016Alice和Bob又在玩游戏

Posted cjoiershiina-mashiro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UOJ 266 清华集训2016Alice和Bob又在玩游戏相关的知识,希望对你有一定的参考价值。

Link
Multi-SG模板题。
(sg_u)(u)子树的SG函数值,(S_u)(u)到删除根节点的路径之后剩下的游戏的SG函数值的异或和。
根节点的(S)就是它所有子树的SG函数值的疑惑和。
在求出(S_u)之后,它的所有儿子(v)(S_v)需要异或上(S_uoplus sg_v)
然后(sg_u=operatorname{mex}{S_v|vin son_u})
那么使用Trie树维护一下就好了。

#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
namespace IO
{
    char ibuf[(1<<21)+1],*iS,*iT;
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
}
using IO::read;
const int N=100007,M=4000007;
std::vector<int>e[N];
int cnt,t,ch[M][2],tag[M],size[M],vis[N],sg[N],root[N];
#define lc ch[x][0]
#define rc ch[x][1]
void pushup(int x){size[x]=size[lc]+size[rc];}
void pushdown(int x,int d)
{
    if(!tag[x]) return ;
    if(tag[x]>>d&1) std::swap(lc,rc);
    tag[lc]^=tag[x],tag[rc]^=tag[x],tag[x]=0;
}
void newnode(int&x){x=++cnt,tag[x]=lc=rc=0,size[x]=1;}
int merge(int x,int y,int d)
{
    if(!x||!y) return x+y;
    pushdown(x,d),pushdown(y,d),lc=merge(lc,ch[y][0],d-1),rc=merge(rc,ch[y][1],d-1);
    if(lc||rc) pushup(x);
    return x;
}
void insert(int&x,int v,int d)
{
    if(!x) newnode(x);
    if(!~d) return ;
    pushdown(x,d),insert(ch[x][v>>d&1? 1:0],v,d-1),pushup(x);
}
int query(int x,int d)
{
    if(!~d) return 0;
    pushdown(x,d);
    return size[lc]<1<<d? query(lc,d-1):query(rc,d-1)|1<<d;
}
void dfs(int u,int fa)
{
    vis[u]=t;int s=0;
    for(std::vector<int>::iterator it=e[u].begin();it!=e[u].end();++it) if(*it^fa) dfs(*it,u),s^=sg[*it];
    for(std::vector<int>::iterator it=e[u].begin();it!=e[u].end();++it) if(*it^fa) tag[root[*it]]^=s^sg[*it],root[u]=merge(root[u],root[*it],16);
    insert(root[u],s,16),sg[u]=query(root[u],16);
}
void work()
{
    int n=read(),m=read(),ans=0;
    ++t,memset(sg+1,0,n<<2),memset(root+1,0,n<<2);
    for(int i=1;i<=n;++i) e[i].clear();
    for(int i=1,u,v;i<=m;++i) u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
    for(int i=1;i<=n;++i) if(vis[i]^t) cnt=0,dfs(i,0),ans^=sg[i];
    puts(ans?"Alice":"Bob");
}
int main(){for(int t=read();t;--t)work();}

以上是关于UOJ 266 清华集训2016Alice和Bob又在玩游戏的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ4730][清华集训2016][UOJ266] Alice和Bob又在玩游戏

博弈论总结

清华集训2016Alice和Bob又在玩游戏

UOJ274清华集训2016温暖会指引我们前行 LCT

bzoj 4736 /uoj274清华集训2016温暖会指引我们前行 lct

UOJ #276. 清华集训2016汽水