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

题目链接

  • 【SG函数】使用01Trie可以支持动态查询当前集合的mex值
  • 如果删除操作发生在根,那后继局面的SG函数值可以直接通过SG定理求出
  • 如果删除操作发生在子树,那根据SG定理,后继局面的SG函数值需要在原来的基础上统一异或上一个数
#include <bits/stdc++.h>
using namespace std;
vector<int>a[100005];
bool v[100005];
int tot,t[100000*18+5][2],s[100000*18+5],bj[100000*18+5];
int sg[100005];
void pushdown(int p,int k)
{
	if((bj[p]>>k)&1)
	{
		swap(t[t[p][0]][0],t[t[p][0]][1]);
		swap(t[t[p][1]][0],t[t[p][1]][1]);
	}
	bj[t[p][0]]^=bj[p];
	bj[t[p][1]]^=bj[p];
	bj[p]=0;
}
int merge(int p,int q,int x,int k)
{
	if(k==-2)
	{
		return 0;
	}
	if(!p&&!q)
	{
		return 0;
	}
	if(!p)
	{
		if((x>>k)&1)
		{
			swap(t[q][0],t[q][1]);
		}
		bj[q]^=x;
		return q;
	}
	if(!q)
	{
		return p;
	}
	if(k>=1)
	{
		pushdown(p,k-1);
		pushdown(q,k-1);
	}
	t[p][0]=merge(t[p][0],t[q][(x>>k)&1],x,k-1);
	t[p][1]=merge(t[p][1],t[q][((x>>k)&1)^1],x,k-1);
	s[p]=s[t[p][0]]+s[t[p][1]]+(k==-1);
	return p;
}
int ask(int p,int k)
{
	if(p==0||k==-1)
	{
		return 0;
	}
	if(s[t[p][0]]==(1<<k))
	{
		return (1<<k)+ask(t[p][1],k-1);
	}
	else
	{
		return ask(t[p][0],k-1);
	}
}
void insert(int p,int x,int k)
{
	if(k==-1)
	{
		s[p]=1;
		return;
	}
	if(!t[p][(x>>k)&1])
	{
		t[p][(x>>k)&1]=++tot;
		t[tot][0]=t[tot][1]=s[tot]=bj[tot]=0;
	}
	insert(t[p][(x>>k)&1],x,k-1);
	s[p]=s[t[p][0]]+s[t[p][1]];
}
void dfs(int n1,int fa)
{
	v[n1]=true;
	int sum=0;
	for(int i=0;i<a[n1].size();i++)
	{
		if(a[n1][i]!=fa)
		{
			dfs(a[n1][i],n1);
			sum=sum^sg[a[n1][i]];
		}
	}
	for(int i=0;i<a[n1].size();i++)
	{
		if(a[n1][i]!=fa)
		{
			sum=sum^sg[a[n1][i]];
			merge(n1,a[n1][i],sum,16);
			sum=sum^sg[a[n1][i]];
		}
	}
	insert(n1,sum,16);
	sg[n1]=ask(n1,16);
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		int n,m;
		cin>>n>>m;
		for(int i=1;i<=n;i++)
		{
			v[i]=false;
			a[i].clear();
			t[i][0]=t[i][1]=s[i]=bj[i]=0;
			sg[i]=0;
		}
		for(int i=1;i<=m;i++)
		{
			int u,v;
			cin>>u>>v;
			a[u].push_back(v);
			a[v].push_back(u);
		}
		int ans=0;
		tot=n;
		for(int i=1;i<=n;i++)
		{
			if(!v[i])
			{
				dfs(i,0);
				ans=ans^sg[i];
			}
		}
		if(ans==0)
		{
			cout<<"Bob\n";
		}
		else
		{
			cout<<"Alice\n";
		}
	}
	return 0;
}
posted @ 2024-11-05 07:59  D06  阅读(10)  评论(0)    收藏  举报
//雪花飘落效果