bzoj 2819: Nim 树状数组+dfs序

来源:互联网 发布:淘宝定做衣服 编辑:程序博客网 时间:2024/05/16 03:03

题意

给一棵树,要求资辞两个操作:
Q x y询问x到y路径上的异或和是否为0.
C x y将x的权值改为y
n,q<=500000

分析

这题一眼过去的想法就是树剖嘛,结果log2发现会爆炸。。。
其实我们只要维护每个点到根的路径异或和就好了。
那么考虑每修改一个点会影响到哪些点,显然就是它子树内的点啦!
那么我们只要用dfs序或树剖序,然后每次修改的时候用树状数组差分一下就好啦。
我打的是树剖,因为我觉得树剖不仅空间更棒棒,而且求lca也很方便啊。
顺便说一句,bzoj貌似是linux下评测,所以是不会爆栈哒。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;const int N=500005;int n,q,cnt,last[N],a[N],size[N],top[N],fa[N],mn[N],mx[N],dep[N],sz,c[N];struct edge{int to,next;}e[N*2];int read(){    int x=0,f=1;char ch=getchar();    while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}void addedge(int u,int v){    e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;    e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;}void dfs1(int x){    dep[x]=dep[fa[x]]+1;size[x]=1;    for (int i=last[x];i;i=e[i].next)    {        if (e[i].to==fa[x]) continue;        fa[e[i].to]=x;        dfs1(e[i].to);        size[x]+=size[e[i].to];    }}void dfs2(int x,int chain){    mn[x]=mx[x]=++sz;top[x]=chain;int k=0;    for (int i=last[x];i;i=e[i].next)        if (e[i].to!=fa[x]&&size[e[i].to]>size[k]) k=e[i].to;    if (!k) return;    dfs2(k,chain);    for (int i=last[x];i;i=e[i].next)        if (e[i].to!=fa[x]&&e[i].to!=k) dfs2(e[i].to,e[i].to);    mx[x]=sz;}int get_lca(int x,int y){    while (top[x]!=top[y])    {        if (dep[top[x]]<dep[top[y]]) swap(x,y);        x=fa[top[x]];    }    if (dep[x]<dep[y]) return x;    else return y;}void ins(int x,int y){    while (x<=n)    {        c[x]^=y;        x+=x&(-x);    }}int query(int x){    int ans=0;    while (x)    {        ans^=c[x];        x-=x&(-x);    }    return ans;}int main(){    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);    }    dfs1(1);    dfs2(1,1);    for (int i=1;i<=n;i++) ins(mn[i],a[i]),ins(mx[i]+1,a[i]);    q=read();    while (q--)    {        char ch[2];        scanf("%s",ch);        if (ch[0]=='Q')        {            int x=read(),y=read(),lca=get_lca(x,y);            if (query(mn[x])^query(mn[y])^a[lca]) puts("Yes");            else puts("No");        }        else        {            int x=read(),y=read();            ins(mn[x],a[x]);ins(mx[x]+1,a[x]);            a[x]=y;            ins(mn[x],y);ins(mx[x]+1,y);        }    }    return 0;}