zoukankan      html  css  js  c++  java
  • BZOJ4134 : ljw和lzr的hack比赛

    设$f[x]$为$x$子树里的子游戏的sg值,$h[x]$为$x$所有儿子节点$f[x]$的异或和,则:

    $f[x]=mex(y到x路径上所有点的h的异或和 xor y到x路径上所有点的f的异或和)$,$y$是$x$子树中的一个白点。

    考虑一个白点对其祖先的影响,可以发现每往上走一步,一个子树里的贡献将会异或上一个相同的数。

    用Trie来维护每个点子树里所有白点的贡献,需要支持合并操作、mex的查询,以及一个异或的标记,下传时交换左右儿子。

    时间复杂度$O(nlog n)$。

    #include<cstdio>
    const int N=100010,M=4000000;
    int n,m,i,x,y,a[N],g[N],v[N<<1],nxt[N<<1],ed,f[N],h[N];
    int l[M],r[M],tag[M],T[N],tot;bool val[M],fin[N];
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
    inline void rev(int d,int p,int x){
      if(!x||d<0)return;
      tag[x]^=p;
      if(p>>d&1){int t=l[x];l[x]=r[x];r[x]=t;}
    }
    inline void pb(int d,int x){if(tag[x])rev(d-1,tag[x],l[x]),rev(d-1,tag[x],r[x]),tag[x]=0;}
    int build(int d,int p){
      int x=++tot;
      if(d<0)return val[x]=1,x;
      if(p>>d&1)r[x]=build(d-1,p);else l[x]=build(d-1,p);
      return x;
    }
    int merge(int d,int p,int x,int y){
      if(!y)return x;
      if(!x){
        rev(d,p,y);
        return y;
      }
      int z=++tot;
      if(d<0)return val[z]=1,z;
      pb(d,x),pb(d,y);
      if(p>>d&1)l[z]=merge(d-1,p,l[x],r[y]),r[z]=merge(d-1,p,r[x],l[y]);
      else l[z]=merge(d-1,p,l[x],l[y]),r[z]=merge(d-1,p,r[x],r[y]);
      return val[z]=val[l[z]]&val[r[z]],z;
    }
    inline int mex(int x){
      int t=0;
      for(int i=m;~i;i--){
        pb(i,x);
        if(!val[l[x]])x=l[x];else x=r[x],t|=1<<i;
      }
      return t;
    }
    void dfs(int x,int y){
      for(int i=g[x];i;i=nxt[i])if(v[i]!=y)dfs(v[i],x),h[x]^=f[v[i]];
      if(!a[x])T[x]=build(m,h[x]);
      for(int i=g[x];i;i=nxt[i])if(v[i]!=y)T[x]=merge(m,h[x]^f[v[i]],T[x],T[v[i]]);
      f[x]=mex(T[x]);
    }
    void cal(int x,int y,int z){
      z^=f[x]^h[x];
      if(!a[x]&&!z)fin[x]=1;
      for(int i=g[x];i;i=nxt[i])if(v[i]!=y)cal(v[i],x,z);
    }
    int main(){
      for(read(n),i=1;i<=n;i++)read(a[i]);
      for(i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x);
      while((1<<m)<=n)m++;m--;
      dfs(1,0);
      if(!f[1])return puts("-1"),0;
      for(cal(i=1,0,f[1]);i<=n;i++)if(fin[i])printf("%d
    ",i);
      return 0;
    }
    

      

  • 相关阅读:
    pandas之DataFrame
    python浅拷贝和深拷贝
    Numpy 机器学习三剑客之Numpy
    django--验证码功能实现
    python基础题
    python武器库
    django-rest-framework
    django--admin组件
    【转载】关于DBUtils中QueryRunner的一些解读
    【转载】java中的反射
  • 原文地址:https://www.cnblogs.com/clrs97/p/5006078.html
Copyright © 2011-2022 走看看