记录编号 450748 评测结果 AAAAAAAAAA
题目名称 [ICPC 2017西安区域赛]树上异或xor 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.380 s
提交时间 2017-09-16 18:01:16 内存使用 102.38 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
const int SIZEN=50010,SIZELOG=20,SIZEQ=510;
const int SQTN=500;
int N,Q,LOGN;
int A[SIZEN]={0};
vector<int> c[SIZEN];
int grand[SIZEN][SIZELOG]={0};
int depth[SIZEN]={0};
int gxor[SIZEN][SIZEQ]={0};
int jump_up(int a,int k){
    int pwd=1;
    for(int i=0;i<=LOGN;i++){
        if(k&pwd){
            a=grand[a][i];
            k^=pwd;
        }
        pwd<<=1;
        if(!k) break;
    }
    return a;
}
int LCA(int a,int b){//a和b的距离
	if(depth[a]>depth[b]) swap(a,b);//a在上面b在下面
	//上下不能弄反
	for(int i=LOGN;i>=0;i--) if(depth[a]<depth[b]&&depth[grand[b][i]]>=depth[a]) b=grand[b][i];
	for(int i=LOGN;i>=0;i--) if(grand[a][i]!=grand[b][i]) a=grand[a][i],b=grand[b][i];
	if(a!=b) a=grand[a][0],b=grand[b][0];//现在a和b再往上走一步就是LCA了
    //否则它们就是LCA,这个if不加会错
    return a;
}
int calc(int a,int k,int mndep){
    if(depth[a]<mndep) return 0;
    int h=depth[a]-mndep;
    int hp=((h/k)+1)*k;
    int a1=jump_up(a,hp);
    //cout<<a<<" "<<k<<" "<<h<<" "<<hp<<endl;
    //cout<<a<<" "<<k<<" "<<mndep<<" "<<hp<<" "<<(gxor[a][k]^gxor[a1][k])<<endl;
    return gxor[a][k]^gxor[a1][k];
}
int query(int a,int b,int k){
    int g=LCA(a,b);
    if(k<=SQTN){
        int r=(depth[a]+depth[b]-2*depth[g])%k;
        int b1=jump_up(b,r);
        int ans=calc(a,k,depth[g])^calc(b1,k,depth[g]+1);
        return ans;
    }
    else{
        int r=(depth[a]+depth[b]-2*depth[g])%k;
        b=jump_up(b,r);
        int ans=0;
        while(depth[a]>=depth[g]){
            ans^=A[a];
            a=jump_up(a,k);
        }
        while(depth[b]>depth[g]){
            ans^=A[b];
            b=jump_up(b,k);
        }
        return ans;
    }
}
void DFS(int x){
	for(int i=1;i<=LOGN;i++){
		grand[x][i]=grand[grand[x][i-1]][i-1];
		if(!grand[x][i]) break;
	}
    for(int i=1;i<=SQTN;i++) gxor[x][i]=A[x];
    //if(x==2) cout<<gxor[x][1]<<endl;
    int y=x;
    for(int i=1;i<=SQTN;i++){
        y=grand[y][0];
        if(!y) break;
        gxor[x][i]^=gxor[y][i];
    }
	for(int i=0;i<c[x].size();i++){
		int u=c[x][i];
		if(u!=grand[x][0]){
			depth[u]=depth[x]+1;
			grand[u][0]=x;
			DFS(u);
		}
	}
}
void work(void){
    depth[0]=-1;
    depth[1]=0;
    DFS(1);
    /*for(int i=1;i<=N;i++){
        for(int j=1;j<=2;j++) cout<<gxor[i][j]<<" ";
        cout<<endl;
    }*/
    int a,b,k;
    for(int i=1;i<=Q;i++){
        scanf("%d%d%d",&a,&b,&k);
        printf("%d\n",query(a,b,k));
    }
}
bool read(void){
    if(scanf("%d%d",&N,&Q)==EOF) return false;
    LOGN = floor(log(N+0.0)/log(2.0));
    //SQTN = sqrt(N+1.0);
    for(int i=0;i<=N;i++){
        c[i].clear();
        depth[i]=0;
        for(int j=0;j<=LOGN;j++) grand[i][j]=0;
        for(int j=0;j<=SQTN;j++) gxor[i][j]=0;
    }
    for(int i=1;i<N;i++){
        int a,b;scanf("%d%d",&a,&b);
        c[a].push_back(b);
        c[b].push_back(a);
    }
    for(int i=1;i<=N;i++) scanf("%d",&A[i]);
    return true;
}
int main(){
    freopen("xor_xian.in","r",stdin);
    freopen("xor_xian.out","w",stdout);
    while(read()){
        work();
    }
    return 0;
}