HDU 5274 Dylans loves tree 树链剖分(水)

来源:互联网 发布:采购流程及优化 编辑:程序博客网 时间:2024/05/16 11:51
HDU 5274
题意:n个节点的树,第i个节点权值为a[i].Q次操作.
操作1:修改a[x]的点权为y
操作2;询问[x,y]路径中是否有权值出现奇数次(保证出现奇数次的权值最多一个)
n,Q,a[i]<=1e5


修改点权 查询路径中是否有点权出现奇数次.

树链剖分后 维护区间的异或和即可. 注意权值可能为0 全部离散化,每个值+1,最后答案减去1即可.

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=4e5+20;int n,Q,cnt,sz;int v[N],dep[N],size[N],head[N],fa[N];int pos[N],bl[N];struct edge{int to,next;}e[N];struct node{int l,r,sum;}t[N<<2];void add_edge(int u,int v){e[++cnt].to=v,e[cnt].next=head[u],head[u]=cnt;}void init(){    memset(head,-1,sizeof(head));    sz=cnt=0;//    scanf("%d%d",&n,&Q);    for(int i=1;i<=n-1;i++)    {        int x,y;        scanf("%d%d",&x,&y);        add_edge(x,y);        add_edge(y,x);    }    for(int i=1;i<=n;i++)        scanf("%d",&v[i]),v[i]++;}void dfs(int u){    size[u]=1;    for(int i=head[u];i!=-1;i=e[i].next)    {        int v=e[i].to;        if(v==fa[u])            continue;        dep[v]=dep[u]+1,fa[v]=u;        dfs(v);        size[u]+=size[v];    }}void dfs(int x,int chain){    int k=0;sz++;    pos[x]=sz;//time;    bl[x]=chain;    for(int i=head[x];i!=-1;i=e[i].next)    {        int v=e[i].to;        if(dep[v]>dep[x]&&size[v]>size[k])            k=v;    }    if(k==0)       return;    dfs(k,chain);    for(int i=head[x];i!=-1;i=e[i].next)        if(dep[e[i].to]>dep[x]&&k!=e[i].to)            dfs(e[i].to,e[i].to);}void build(int o,int l,int r){    t[o].l=l,t[o].r=r,t[o].sum=0;    if(l==r)        return;    int m=l+r>>1;    build(o<<1,l,m);    build(o<<1|1,m+1,r);}void push_up(int o){    t[o].sum=t[o<<1].sum ^ t[o<<1|1].sum;}void change(int o,int x,int y){    int l=t[o].l,r=t[o].r,mid=l+r>>1;    if(l==r)    {        t[o].sum=y;        return;    }    if(x<=mid)        change(o<<1,x,y);    else        change(o<<1|1,x,y);    push_up(o);}int querysum(int o,int ql,int qr){    int l=t[o].l,r=t[o].r,m=l+r>>1;    if(ql<=l&&qr>=r)        return t[o].sum;    int res=0;    if(ql<=m)        res^=querysum(o<<1,ql,qr);    if(qr>m)        res^=querysum(o<<1|1,ql,qr);    return res;}int solvesum(int x,int y){    int res=0;    while(bl[x]!=bl[y])    {        if(dep[bl[x]]<dep[bl[y]])            swap(x,y);        res^=querysum(1,pos[bl[x]],pos[x]);        x=fa[bl[x]];    }    if(pos[x]>pos[y])        swap(x,y);    res^=querysum(1,pos[x],pos[y]);    return res;}void solve(){    build(1,1,n);    for(int i=1;i<=n;i++)        change(1,pos[i],v[i]);    int op,x,y;    while(Q--)    {        scanf("%d%d%d",&op,&x,&y);        if(op==0)            ++y,change(1,pos[x],y);        else        {            int val=solvesum(x,y);            printf("%d\n",val-1);        }    }}int main(){    int T;    cin>>T;    while(T--)    {        init();        dfs(1);        dfs(1,1);        solve();    }    return 0;}