1. 程式人生 > >2017 ACM-ICPC 亞洲區(西安賽區)網路賽 G. Xor

2017 ACM-ICPC 亞洲區(西安賽區)網路賽 G. Xor

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxed=50000+10;
struct E
{
    int v,bef;
}e[maxed*2];
int n,m,ans,head[maxed],p[maxed];
int top[maxed],son[maxed],size_[maxed],d[maxed];
int f[maxed][20],sxor_[maxed][255];
int main()
{
    //freopen("shuJu.txt","w",stdout);
    void add_(int,int);
    void slove_1(int,int);
    void slove_2(int,int);
    int lca(int,int);
    int find_(int,int);
    while(scanf("%d%d",&n,&m)!=EOF){
        ans=1;
        memset(head,-1,sizeof(head));
        int a,b,c;
        for(int i=1;i<=n-1;i++){
            scanf("%d%d",&a,&b);
            add_(a,b);
            add_(b,a);
        }
        memset(f,0,sizeof(f));
        for(int i=1;i<=n;i++){
            scanf("%d",&p[i]);
            son[i]=0;
            if (i == 1)
                f[i][0] = 0;
            else
                f[i][0] = i;
        }
        d[0] = 0;
        memset(sxor_,0,sizeof(sxor_));
        slove_1(1,1);
        slove_2(1,1);
        for(int i=1;i<=20;i++)
            for(int j=1;j<=n;j++){
                int r=f[j][i-1];
                if(r==0)
                    continue;
                f[j][i]=f[r][i-1];
            }
        int len=(int)sqrt(n);
        while(m--){
            scanf("%d%d%d",&a,&b,&c);
            int wa=lca(a,b);
            if(c<=len){
                int answer=sxor_[a][c];
                int k=c-(d[a]-d[wa])%c;
                int kk=find_(wa,k);
                answer^=sxor_[kk][c];
                if (d[b] - d[wa] - k >= 0 && b != wa) {
                    kk = (d[b] - d[wa] - k)%c;
                    int r = find_(b, kk);
                    answer ^= sxor_[r][c];
                    kk = (d[a] - d[wa])%c;
                    k = find_(wa, kk);
                    answer ^= sxor_[k][c];
                }
                printf("%d\n", answer);
            }
            else{
                int answer = 0, l = a, r = b;
                while (d[l] >= d[wa]){
                    answer ^= p[l];
                    l = find_(l, c);
                }
                if (d[r] - d[wa] - (c - (d[a] - d[wa])%c) >= 0 && b != wa) {
                    int k = (d[r] - d[wa] - (c - (d[a] - d[wa])%c))%c;
                    r = find_(r, k);
                    while (d[r] > d[wa]) {
                        answer ^= p[r];
                        r = find_(r, c);
                    }
                }
                printf("%d\n", answer);
            }
        }
    }
    return 0;
}
void add_(int x,int y)
{
    e[ans].v=y;
    e[ans].bef=head[x];
    head[x]=ans++;
}
void slove_1(int u,int dep)
{
    size_[u]=1;
    d[u]=dep;
    int now=u,step=0;
    while(step<255){
        sxor_[u][step]=p[u]^sxor_[now][step];
        now = f[now][0];
        step++;
    }
    for(int i=head[u];i!=-1;i=e[i].bef){
        int v=e[i].v;
        if (f[u][0] == v)
            continue;
        f[v][0] = u;
        slove_1(v,dep+1);
        size_[u]+=size_[v];
        if(!son[u]||size_[son[u]]<size_[v])
            son[u]=v;
    }
}
void slove_2(int u,int fa)
{
    top[u]=fa;
    if(son[u])
        slove_2(son[u],fa);
    for(int i=head[u];i!=-1;i=e[i].bef){
        int v=e[i].v;
        if (f[u][0] == v || son[u] == v)
            continue;
        slove_2(v,v);
    }
}
int lca(int a,int b)
{
    int f1=top[a],f2=top[b],l=a,r=b;
    while(f1!=f2){
        if(d[f1]<d[f2]){
            swap(f1,f2);
            swap(l,r);
        }
        l = f[f1][0];
        f1=top[l];
    }
    if(d[l]>d[r])
        swap(l,r);
    return l;
}
int find_(int a,int x)
{
    int s=0;
    while(x){
        if(x&1)
            a=f[a][s];
        x>>=1;
        s++;
    }
    return a;
}