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


    题目链接:Alice和Bob又在玩游戏

      这道题就是一个很显然的公平游戏。

      首先(O(n^2))的算法非常好写。暴力枚举每个后继计算(mex)即可。注意计算后继的时候可以直接从父亲转移过来,没必要(O(n))扫一遍所有节点 。

      然后我们仔细看看转移,就可以发现这玩意儿就是一个集合,每次要支持集合异或上一个数,集合插入一个数,以及集合合并。然后我们用(Trie)树(其实就是线段树)来维护即可。每个节点记录一个(size),就可以从顶往下找(mex)了。

      下面贴代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    #define maxn 100010
    #define MAXN 1600010
    
    using namespace std;
    typedef long long llg;
    
    int T,n,m,sg[maxn],ans;
    int head[maxn],next[maxn<<1],to[maxn<<1],tt;
    int s[MAXN][2],rt[maxn],ao[MAXN],siz[MAXN];
    bool vis[maxn];
    
    int getint(){
    	int w=0;bool q=0;
    	char c=getchar();
    	while((c>'9'||c<'0')&&c!='-') c=getchar();
    	if(c=='-') c=getchar(),q=1;
    	while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
    	return q?-w:w;
    }
    
    int pop(){int u=++tt;s[u][0]=s[u][1]=ao[u]=0;siz[u]=1;return u;}
    void link(int x,int y){
    	to[++tt]=y;next[tt]=head[x];head[x]=tt;
    	to[++tt]=x;next[tt]=head[y];head[y]=tt;
    }
    
    void pudn(int u,int k){
    	if((ao[u]>>k)&1) swap(s[u][0],s[u][1]);
    	int o=ao[u]&((1<<k)-1); ao[u]=0;
    	ao[s[u][0]]^=o;ao[s[u][1]]^=o;
    }
    
    int merge(int u,int v,int k){
    	if(!u || !v) return u+v;
    	pudn(u,k); pudn(v,k);
    	s[u][1]=merge(s[u][1],s[v][1],k-1);
    	s[u][0]=merge(s[u][0],s[v][0],k-1);
    	return u;
    }
    
    int getans(int u){
    	int now=0;
    	for(int i=16;i>=0;i--){
    		now<<=1;
    		if(siz[s[u][0]]<(1<<i)) u=s[u][0];
    		else u=s[u][1],now|=1;
    	}
    	return now;
    }
    
    void ins(int &u,int x,int k){
    	if(!u) u=pop();
    	if(k>=0){
    		pudn(u,k); ins(s[u][(x>>k)&1],x,k-1);
    		siz[u]=siz[s[u][0]]+siz[s[u][1]];
    	}
    }
    
    void dfs(int u,int fa){
    	vis[u]=1; int now=0;
    	for(int i=head[u],v;v=to[i],i;i=next[i])
    		if(v!=fa) dfs(v,u),now^=sg[v];
    	for(int i=head[u],v;v=to[i],i;i=next[i])
    		if(v!=fa) ao[rt[v]]^=now^sg[v],rt[u]=merge(rt[u],rt[v],16);
    	ins(rt[u],now,16),sg[u]=getans(rt[u]);
    }
    
    int main(){
    	File("a");
    	T=getint();
    	while(T--){
    		n=getint(),m=getint(); ans=tt=0;
    		while(m--) link(getint(),getint());
    		for(int i=1;i<=n;i++)
    			if(!vis[i]) tt=0,dfs(i,0),ans^=sg[i];
    		printf(ans?"Alice
    ":"Bob
    ");
    		for(int i=1;i<=n;i++) rt[i]=sg[i]=head[i]=vis[i]=0;
    	}
    	return 0;
    }
    

       BZOJ提交网址:BZOJ 4730 Alice和Bob又在玩游戏

  • 相关阅读:
    ASP.NET在禁用视图状态的情况下仍然使用ViewState对象【转】
    Atcoder Regular Contest 061 D Card Game for Three(组合数学)
    Solution 「CERC 2016」「洛谷 P3684」机棚障碍
    Solution 「CF 599E」Sandy and Nuts
    Solution 「洛谷 P6021」洪水
    Solution 「ARC 058C」「AT 1975」Iroha and Haiku
    Solution 「POI 2011」「洛谷 P3527」METMeteors
    Solution 「CF 1023F」Mobile Phone Network
    Solution 「SP 6779」GSS7
    Solution 「LOCAL」大括号树
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/6529418.html
Copyright © 2020-2023  润新知