hdu5274 Dylans loves tree

来源:互联网 发布:如皋淘宝 编辑:程序博客网 时间:2024/05/16 15:58
官方题解
题目里有一个很神奇的性质:路径上最多只有一个数出现奇数次。这应该马上想到异或。因为异或两次和没异或是等价的。此外异或满足区间减性质。因为有修改,我们很自然地想到用数据结构维护。最无脑的就是直接上树链剖分或是Splay维护区间xor值即可。仔细想一想,发现可以利用LCA消去“树上路径”,转化为根到x路径上求xor值。我们可以很经典地直接使用线段树或树状数组维护dfs序。(然而BC不给我卡log2。。。呜呜呜)有一个很强的trick就是权值可以为0!所以比如路径上有3个0,虽然他们xor值还是0,但是他们是出现了奇数次。我特意把A[i]说成∈自然数集而不是[0,100000],就是想尽量不被发现。怎么避免呢?单独维护0的情况?有一个很简单的解决方案:直接把读入时所有权值+1,输出的时候再-1即可!
#include<iostream>#include<cstdio>#include<cstring>#include<vector>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;const int maxn=100005;int d[maxn];int deep[maxn];int dp[maxn][21];int tree[maxn];int st[maxn],ed[maxn];vector<int>g[maxn];int n,q;int o;void dfs(int rt,int f,int sh){    st[rt]=++o;    deep[rt]=sh;    if(f==-1)        dp[rt][0]=rt;    else        dp[rt][0]=f;    for(int i=1;i<=20;i++){        dp[rt][i]=dp[dp[rt][i-1]][i-1];    }    for(int i=0;i<g[rt].size();i++){        if(g[rt][i]==f)            continue;        dfs(g[rt][i],rt,sh+1);    }    ed[rt]=o+1;}int lca(int a,int b){    int deep1=deep[a];    int deep2=deep[b];    if(deep1<deep2){        swap(deep1,deep2);        swap(a,b);    }    int y=deep1-deep2;    for(int i=0;i<=20;i++){        if(y&(1<<i)){            a=dp[a][i];        }    }    if(a==b)        return a;    for(int i=20;i>=0;i--){        if(dp[a][i]==dp[b][i])            continue;        a=dp[a][i];        b=dp[b][i];    }    return dp[a][0];}int lowbit(int x){    return x&(-x);}void update(int a,int x){    while(a<=o){        tree[a]^=x;        a+=lowbit(a);    }}int query(int x){    int ans=0;    while(x>0){        ans^=tree[x];        x-=lowbit(x);    }    return ans;}int main(){    int t;    int a,b;    scanf("%d",&t);    while(t--){        o=0;        scanf("%d%d",&n,&q);        for(int i=1;i<=n;i++)            g[i].clear();        for(int i=0;i<n-1;i++){            scanf("%d%d",&a,&b);            g[a].push_back(b);            g[b].push_back(a);        }        for(int i=1;i<=n;i++){            scanf("%d",&d[i]);            d[i]++;        }        dfs(1,-1,0);        memset(tree,0,sizeof(tree));        for(int i=1;i<=n;i++){            update(st[i],d[i]);            update(ed[i],d[i]);        }        int c;        for(int i=0;i<q;i++){            scanf("%d%d%d",&c,&a,&b);            if(c==0){                update(st[a],d[a]);                update(ed[a],d[a]);                d[a]=b+1;                update(st[a],d[a]);                update(ed[a],d[a]);            }            else{                int ans=query(st[a])^query(st[b])^d[lca(a,b)];                if(ans==0)                    printf("-1\n");                else                    printf("%d\n",ans-1);            }        }    }    return 0;}


O(Nlog(N))
0 0
原创粉丝点击