zoukankan      html  css  js  c++  java
  • [BZOJ4730][清华集训2016][UOJ266] Alice和Bob又在玩游戏

    题意:俩智障又在玩游戏。规则如下:

    给定n个点,m条无向边(m<=n-1),保证无环,对于每一个联通块,编号最小的为它们的根(也就是形成了一片这样的森林),每次可以选择一个点,将其本身与其祖先全部删除,不能操作者输。判断先手胜负。

    题解:比较神的一道题。

    我们现在要解决的问题是怎么求解一棵子树的SG值,首先把根删掉的情况考虑,这很好办,直接把子树的sg异或起来就好,关键是如果删除点在子树里怎么办。

    这里用到了一个巧妙的东西,trie。怎么会用这个呢?因为删除子树里的节点就相当于是子树里这种对应的情况再异或上外边子树的sg。但是我们不可能用一般的方法来存一棵子树里所有的sg。这个时候trie应运而生。我们处理子树之后,把它合并上来,就能得到当前节点的所有拓展局面的sg了。这里注意,合并子树前要先在子树上打一个tag(因为它是要异或上外面所有子树sg的)。

    算法很清晰了,dfs下去,合并上来。这里的trie还要打tag。所有细节就这么多。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long
     4 #define N 100005
     5  
     6 inline LL read(){
     7        LL x=0,f=1; char a=getchar();
     8        while(a<'0' || a>'9') {if(a=='-') f=-1; a=getchar();}
     9        while(a>='0' && a<='9') x=x*10+a-'0',a=getchar();
    10        return x*f;
    11 }
    12  
    13 int n,m,T,bin[25],head[N],cnt,id,tag[N*20],rt[N],ls[N*20],rs[N*20],sg[N],sz[N*20];
    14 bool vis[N];
    15  
    16 struct edges{
    17     int to,next;
    18 }e[2*N];
    19  
    20 inline void insert(){
    21     int u=read(),v=read();
    22     e[++cnt]=(edges){v,head[u]};head[u]=cnt;
    23     e[++cnt]=(edges){u,head[v]};head[v]=cnt;
    24 }
    25  
    26 inline void init(){
    27     bin[0]=1; for(int i=1;i<=19;i++) bin[i]=bin[i-1]<<1;
    28 }
    29  
    30 inline void pushdown(int k,int level){
    31     if(!tag[k]) return;
    32     if(bin[level-1]&tag[k]) swap(ls[k],rs[k]);
    33     tag[ls[k]]^=tag[k]; tag[rs[k]]^=tag[k];
    34     tag[k]=0;
    35 }
    36  
    37 inline void reset(){
    38     for(int i=1;i<=n;i++) head[i]=sg[i]=rt[i]=0,vis[i]=0;
    39     for(int i=1;i<=id;i++) tag[i]=ls[i]=rs[i]=sz[i]=0;
    40     cnt=1; id=0;
    41 }
    42  
    43 void ins(int& k,int x,int level){ // 0 is on the left
    44     k=++id; sz[k]=1;
    45     if(!level) return;
    46     if(x&bin[level-1]) ins(rs[k],x,level-1);
    47     else ins(ls[k],x,level-1);
    48 }
    49  
    50 int merge(int x,int y,int level){
    51     if(!x || !y) return x|y;
    52     pushdown(x,level); pushdown(y,level);
    53     ls[x]=merge(ls[x],ls[y],level-1); rs[x]=merge(rs[x],rs[y],level-1);
    54     sz[x]=sz[ls[x]]+sz[rs[x]]+(level?0:1);
    55     return x;
    56 }
    57  
    58 void dfs(int x,int fa){
    59     vis[x]=1; int t=0;
    60     for(int i=head[x];i;i=e[i].next){
    61         if(fa==e[i].to) continue;
    62         dfs(e[i].to,x); t^=sg[e[i].to];
    63     }
    64     ins(rt[x],t,19);
    65     for(int i=head[x];i;i=e[i].next){
    66         if(fa==e[i].to) continue;
    67         tag[rt[e[i].to]]^=t^sg[e[i].to];
    68         rt[x]=merge(rt[x],rt[e[i].to],19);
    69     }
    70     for(int now=rt[x],i=19;i;i--){ // i is the i th digit int binary system
    71         pushdown(now,i);
    72         if(sz[ls[now]]<bin[i-1]) now=ls[now];
    73         else sg[x]|=bin[i-1],now=rs[now];
    74     }
    75 }
    76  
    77 inline void solve(){
    78     n=read(); m=read(); int ans=0;
    79     for(int i=1;i<=m;i++) insert();
    80     for(int i=1;i<=n;i++) if(!vis[i]) dfs(i,0),ans^=sg[i];
    81     puts(ans?"Alice":"Bob");
    82 }
    83  
    84 int main(){
    85     init(); T=read();
    86     while(T--){
    87         solve();
    88         reset();
    89     }
    90     return 0;
    91 }
  • 相关阅读:
    各国语言缩写列表,各国语言缩写-各国语言简称,世界各国域名缩写
    How to see log files in MySQL?
    git 设置和取消代理
    使用本地下载和管理的免费 Windows 10 虚拟机测试 IE11 和旧版 Microsoft Edge
    在Microsoft SQL SERVER Management Studio下如何完整输出NVARCHAR(MAX)字段或变量的内容
    windows 10 x64系统下在vmware workstation pro 15安装macOS 10.15 Catelina, 并设置分辨率为3840x2160
    在Windows 10系统下将Git项目签出到磁盘分区根目录的方法
    群晖NAS(Synology NAS)环境下安装GitLab, 并在Windows 10环境下使用Git
    使用V-2ray和V-2rayN搭建本地代理服务器供局域网用户连接
    windows 10 专业版安装VMware虚拟机碰到的坑
  • 原文地址:https://www.cnblogs.com/enigma-aw/p/6602252.html
Copyright © 2011-2022 走看看