思路:
可持久化trie树裸题
x->y 就是x +y -lca(x,y) -fa[lca(x,y)]
学了可持久化线段树 再看这个就无压力了
注意是多组数据……
//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100050
#define mem(x,y) memset(x,y,sizeof(x))
int first[N],nxt[N*2],v[N*2],w[N*2],tot,xx,yy,zz,n,m;
int size[N],son[N],fa[N],top[N],deep[N],a[N];
int cnt,ch[N*20][2],wei[N*20],f,root[N];
void add(int x,int y){v[tot]=y,nxt[tot]=first[x],first[x]=tot++;}
void insert(int last,int num){
int now=cnt;
for(int i=16;i>=0;i--){
f=num&(1<<i)?1:0;
ch[now][f]=++cnt;ch[now][!f]=ch[last][!f];
last=ch[last][f],now=ch[now][f];
wei[now]=wei[last]+1;
}
}
void dfs(int x){
size[x]=1,son[x]=0;root[x]=++cnt,insert(root[fa[x]],a[x]);
for(int i=first[x];~i;i=nxt[i])if(v[i]!=fa[x]){
fa[v[i]]=x,deep[v[i]]=deep[x]+1,dfs(v[i]);
size[x]+=size[v[i]];
if(size[v[i]]>size[son[x]])son[x]=v[i];
}
}
void dfs2(int x,int tp){
top[x]=tp;
if(son[x])dfs2(son[x],tp);
for(int i=first[x];~i;i=nxt[i])if(v[i]!=fa[x]&&v[i]!=son[x])
dfs2(v[i],v[i]);
}
int lca(int x,int y){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(deep[fx]<deep[fy])swap(x,y),swap(fx,fy);
x=fa[fx],fx=top[x];
}return deep[x]<deep[y]?x:y;
}
int query(int x,int y,int lca,int flca,int num){
int temp=0;
for(int i=16;i>=0;i--){
f=num&(1<<i)?0:1;
if(wei[ch[x][f]]+wei[ch[y][f]]-wei[ch[lca][f]]-wei[ch[flca][f]]>0)
x=ch[x][f],y=ch[y][f],lca=ch[lca][f],flca=ch[flca][f],temp+=(1<<i);
else x=ch[x][!f],y=ch[y][!f],lca=ch[lca][!f],flca=ch[flca][!f];
}return temp;
}
int main(){
while(~scanf("%d%d",&n,&m)){
mem(first,-1),tot=cnt=0;
mem(ch,0),mem(wei,0);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<n;i++){
scanf("%d%d",&xx,&yy);
add(xx,yy),add(yy,xx);
}
dfs(1),dfs2(1,1);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&xx,&yy,&zz);
int LCA=lca(xx,yy);
printf("%d\n",query(root[xx],root[yy],root[LCA],root[fa[LCA]],zz));
}
}
}
附一个小小的对拍:
maker:
//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
int seed,n,m;
int main(){
freopen("seed.txt","r",stdin);
scanf("%d",&seed);
srand(seed+time(0));rand();rand();rand();rand();rand();
freopen("seed.txt","w",stdout);
printf("%d\n",rand());
freopen("in.txt","w",stdout);
int cases=5;
while(cases--){
n=rand()%100000+1,m=rand()%100000+1;
printf("%d %d\n",n,m);
for(int i=1;i<=n;i++)printf("%d ",rand()%65536);
for(int i=2;i<=n;i++)printf("%d %d\n",i,rand()%(i-1)+1);
for(int i=1;i<=m;i++){
printf("%d %d %d\n",rand()%n+1,rand()%n+1,rand()%65536);
}
}
}
pai:
//By SiriusRen
#include <bits/stdc++.h>
using namespace std;
long int bt,cases;
int main(){
while(1){
bt=clock();
printf("Case %ld\n",++cases);
system("mk.exe");
printf("maker time =%ldms\n",clock()-bt);
bt=clock();
system("a.exe<in.txt>out1.txt");
printf("time a =%ldms\n",clock()-bt);
bt=clock();
system("b.exe<in.txt>out2.txt");
printf("time b =%ldms\n",clock()-bt);
if(system("fc out1.txt out2.txt")){
puts("Wrong Answer~~~");
while(1);
}
}
}