首页 > 技术文章 > CF1149E Election Promises

cjoierShiina-Mashiro 2020-04-09 22:28 原文

Link
首先求出每个点的\(SG\)函数值,即\(SG(u)=\operatorname{mex}\{SG(v)|v\in son_u\}\)
然后求出\(sum_x=\operatorname{xor}\limits_{SG(u_=x}a_u\)
那么先手必胜当且仅当存在\(sum_x\)非零。
如果\(sum\)全为\(0\),那么先手操作\(u\)之后\(sum_{SG(u)}\)一定会变化。
如果存在\(sum_x\)非零,那么我们找到\(x=\max\{x|sum_x>0\}\),然后再任选一个\(u\in\{u|SG(u)=x\wedge a_u>a_u\operatorname{xor} sum_x\}\)
然后我们将\(a_u\)修改为\(a_u\operatorname{xor}sum_x\),这样\(sum_x\)就变成了\(0\)
然后\(\forall i\in[0,x)\),若\(sum_i>0\),就找到\(v\in\{v|v\in son_u\wedge SG(v)=i\}\),然后修改\(a_v\)\(a_v\operatorname{xor}sum_i\)即可。
显然这都是能够找到的,那么我们就将必胜态转化为了必败态。

#include<queue>
#include<cctype>
#include<cstdio>
#include<vector>
const int N=200007;
int a[N],deg[N],pos[N],vis[N],sg[N],sum[N];std::queue<int>q;std::vector<int>e[N];
int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
int main()
{
    int n=read(),m=read();
    for(int i=1;i<=n;++i) a[i]=read();
    for(int i=1,u,v;i<=m;++i) u=read(),v=read(),e[u].push_back(v),++deg[v];
    for(int i=1;i<=n;++i) if(!deg[i]) q.push(i);
    for(int u,c=0;!q.empty();)
    {
	u=q.front(),q.pop(),pos[++c]=u;
	for(int v:e[u]) if(!--deg[v]) q.push(v);
    }
    for(int i=n,u;i;--i)
    {
	u=pos[i];
	for(int v:e[u]) vis[sg[v]]=i;
	while(vis[sg[u]]==i) ++sg[u];
	sum[sg[u]]^=a[u];
    }
    for(int i=n,u;~i;--i)
	if(sum[i])
	{
	    for(int j=1;j<=n;++j) if(sg[j]==i&&a[j]>(sum[i]^a[j])) u=j;
	    a[u]^=sum[i];
	    for(int v:e[u]) a[v]^=sum[sg[v]],sum[sg[v]]=0;
	    puts("WIN");
	    for(int j=1;j<=n;++j) printf("%d ",a[j]);
	    return 0;
	}
    puts("LOSE");
}

推荐阅读