HDU5274.Dylans loves tree

/* 题目里有一个很神奇的性质:路径上最多只有一个数出现奇数次。 这应该马上想到异或。因为异或两次和没异或是等价的。此外异或满足区间减性质。 因为有修改,我们很自然地想到用数据结构维护。 最无脑的就是直接上树链剖分或是Splay维护区间xor值即可。 仔细想一想,发现可以利用LCA消去“树上路径”,转化为根到x路径上求xor值。 我们可以很经典地直接使用线段树或树状数组维护dfs序。 ​有一个很强的trick就是权值可以为0! 所以比如路径上有3个0,虽然他们xor值还是0,但是他们是出现了奇数次。 我特意把A[i]说成∈自然数集而不是[0,100000],就是想尽量不被发现。 怎么避免呢?单独维护0的情况? 有一个很简单的解决方案:直接把读入时所有权值+1,输出的时候再-1即可! 时间复杂度为O(N*log(N)^{2})或者O(N*log(N))O(N∗log(N)) */
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
const int maxn=100000+10;
vector<int>G[maxn];
int deep[maxn];
int top[maxn]; //top[v]表示v所在的链的顶端结点
int siz[maxn];  //siz表示以v为根的子树的结点数
int p[maxn];  //p[v]表示v对应的位置
int son[maxn]; //重儿子
int a[maxn],sumv[4*maxn];
int fa[maxn];
int u,v,L,R,pos;

void init(int n){
    for(int i=1;i<=n;i++)
        G[i].clear();
    mem1(son);
    pos=0;
}

void dfs1(int u,int pre,int d){ //第一遍dfs求出fa,deep,siz,son
    deep[u]=d;
    fa[u]=pre;
    siz[u]=1;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v!=pre){
            dfs1(v,u,d+1);
            siz[u]+=siz[v];
            if(son[u]==-1||siz[v]>siz[son[u]])
                son[u]=v;
        }
    }
}

void getpos(int u,int sp){   //第二遍dfs求出top和p
    top[u]=sp;
    p[u]=++pos;
    if(son[u]==-1)
        return;
    getpos(son[u],sp); //先遍历重莲,重莲的顶端结点为其父亲的顶端结点
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v!=son[u]&&v!=fa[u])
            getpos(v,v);       //轻链的顶端节点ei自己
    }
}

void pushup(int rt){
    sumv[rt]=sumv[rt<<1]^sumv[rt<<1|1];
}

void build(int l,int r,int rt){
    sumv[rt]=0;
    if(l==r)
        return ;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}

void update(int l,int r,int rt){
    if(l==r){
        sumv[rt]=v;
        return ;
    }
    int m=(l+r)>>1;
    if(u<=m)
        update(lson);
    else
        update(rson);
    pushup(rt);
}

int query(int l,int r,int rt){
    int res=0;
    if(L<=l&&R>=r){
        return sumv[rt];
    }
    int m=(l+r)>>1;
    if(L<=m){
        res^=query(lson);
    }
    if(R>m){
        res^=query(rson);
    }
    return res;
}

int find(int u,int v){
    int f1=top[u],f2=top[v];
    int sum=0;
    while(f1!=f2){
        if(deep[f1]<deep[f2]){
            swap(f1,f2);
            swap(u,v);
        }
        L=p[f1];
        R=p[u];
        sum^=query(1,pos,1);
        u=fa[f1];
        f1=top[u];
    }
    if(deep[u]>deep[v])
        swap(u,v);
    L=p[u];
    R=p[v];
    sum^=query(1,pos,1);
    return sum;
}

int main(){
    int n,t,Q;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&Q);
        init(n);
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        dfs1(1,1,0);
        getpos(1,1);
        build(1,pos,1);
        for(int i=1;i<=n;i++){
            u=p[i];
            v=a[i]+1;
            update(1,pos,1);
        }
        int op;
        while(Q--){
            scanf("%d%d%d",&op,&u,&v);
            if(op==1){
                int ans=find(u,v);
                if(ans==0)
                    printf("-1\n");
                else
                    printf("%d\n",ans-1);
            }
            else{
                u=p[u];
                v++;
                update(1,pos,1);
            }
        }
    }
    return 0;
}

你可能感兴趣的:(HDU5274.Dylans loves tree)