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;
    }
    

      

  • 相关阅读:
    轻重搭配
    EF的优缺点
    使用bootstrap-select有时显示“Nothing selected”
    IIS发布 HTTP 错误 500.21
    js添加的元素无法触发click事件
    sql server查看表是否死锁
    sql server把一个库表的某个字段更新到另一张表的相同字段
    SQLSERVER排查CPU占用高的情况
    SQL server中如何按照某一字段中的分割符将记录拆成多条
    LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression.
  • 原文地址:https://www.cnblogs.com/clrs97/p/5006078.html
Copyright © 2011-2022 走看看