bzoj 4134 ljw和lzr的hack比赛

来源:互联网 发布:python网络爬虫是什么 编辑:程序博客网 时间:2024/06/05 19:43

Trie树维护Sg值,类似线段树合并的方式合并子树,复杂度 O(nlog(n))

/**************************************************************    Problem: 4134    User: Clare    Language: C++    Result: Accepted    Time:1988 ms    Memory:73476 kb****************************************************************/ #include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std; #define N 100010 int n,m;int A[N],f[N],h[N],C[40],root[N];struct Edge{    int to,next;}edge[N*2];int head[N],Tot;struct Node{    int l,r,flag;    bool Full,Be_ans;}t[N*40];int tot; inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}    return x*f;} void Addedge(int u,int v){    Tot++;edge[Tot].next=head[u];edge[Tot].to=v;head[u]=Tot;    Tot++;edge[Tot].next=head[v];edge[Tot].to=u;head[v]=Tot;} void Rev(int Floor,int k,int x){    if(!x||Floor<0)        return;    t[x].flag^=k;    if(k&C[Floor])        swap(t[x].l,t[x].r);} void Pushdown(int Floor,int x){    if(t[x].flag)    {        Rev(Floor-1,t[x].flag,t[x].l);        Rev(Floor-1,t[x].flag,t[x].r);        t[x].flag=0;    }} int Build(int Floor,int k){    int now=++tot;    if(Floor<0)    {        t[now].Full=1;        return now;    }    if(k&C[Floor])        t[now].r=Build(Floor-1,k);    else t[now].l=Build(Floor-1,k);    return now;} int Merge(int Floor,int k,int x,int y){    if(!y)        return x;    if(!x)    {        Rev(Floor,k,y);        return y;    }    int now=++tot;    if(Floor<0)    {        t[now].Full=1;        return now;    }    Pushdown(Floor,x);Pushdown(Floor,y);    if(k&C[Floor])    {        t[now].l=Merge(Floor-1,k,t[x].l,t[y].r);        t[now].r=Merge(Floor-1,k,t[x].r,t[y].l);    }    else    {        t[now].l=Merge(Floor-1,k,t[x].l,t[y].l);        t[now].r=Merge(Floor-1,k,t[x].r,t[y].r);    }    t[now].Full=t[t[now].l].Full&t[t[now].r].Full;    return now;} int Mex(int Floor,int x){    if(Floor<0)        return 0;    Pushdown(Floor,x);    if(!t[t[x].l].Full)    {        x=t[x].l;        return Mex(Floor-1,x);    }    else    {        x=t[x].r;        return C[Floor]+Mex(Floor-1,x);    }} void DFS(int k,int fa){    for(int i=head[k];i;i=edge[i].next)    {        int v=edge[i].to;        if(v==fa)            continue;        DFS(v,k);        h[k]^=f[v];    }    if(!A[k])        root[k]=Build(m,h[k]);    for(int i=head[k];i;i=edge[i].next)    {        int v=edge[i].to;        if(v==fa)            continue;        root[k]=Merge(m,h[k]^f[v],root[k],root[v]);    }    f[k]=Mex(m,root[k]);} void Find(int k,int fa,int ans){    ans^=h[k]^f[k];    if(!A[k]&&!ans)        t[k].Be_ans=true;    for(int i=head[k];i;i=edge[i].next)    {        int v=edge[i].to;        if(v==fa)            continue;        Find(v,k,ans);    }} int main(){    C[0]=1;    for(int i=1;i<=30;i++)        C[i]=C[i-1]<<1;    n=read();    for(int i=1;i<=n;i++)        A[i]=read();    for(int i=1;i<n;i++)    {        int x=read(),y=read();        Addedge(x,y);    }    while(C[m]<=n)m++;    m--;    DFS(1,0);    if(!f[1])    {        printf("-1\n");    }    else    {        Find(1,0,f[1]);        for(int i=1;i<=n;i++)        {            if(t[i].Be_ans)                printf("%d\n",i);        }    }    return 0;}


0 0
原创粉丝点击