码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-02-12 22:08:18      阅读:76      评论:0      收藏:0      [点我收藏+]

标签:turn   namespace   pushd   get   efi   query   git   ++i   eof   

Link
Multi-SG模板题。
\(sg_u\)\(u\)子树的SG函数值,\(S_u\)\(u\)到删除根节点的路径之后剩下的游戏的SG函数值的异或和。
根节点的\(S\)就是它所有子树的SG函数值的疑惑和。
在求出\(S_u\)之后,它的所有儿子\(v\)\(S_v\)需要异或上\(S_u\oplus sg_v\)
然后\(sg_u=\operatorname{mex}\{S_v|v\in 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 【清华集训2016】Alice和Bob又在玩游戏

标签:turn   namespace   pushd   get   efi   query   git   ++i   eof   

原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12301037.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!