树上主席树。听上去好像十分高大。。然而其实思路是非常清晰地。//就是在dfs的时候更新新的主席树
然后有一个办法稍微有点巧妙。就是求x,y这一条链上某一段权值的和可以转换为sum[x]+sum[y]-sum[lca(x,y)]-sum[fa(lca(x,y)]
然后因为蒟蒻打lca只会树剖然后代码就稍显的有点长了。。。
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include<map>
#include<list>
#define pb push_back
#define lb lower_bound
#define sqr(x) (x)*(x)
#define lowbit(x) (x)&(-x)
#define Abs(x) ((x) > 0 ? (x) : (-(x)))
#define forup(i,a,b) for(int i=(a);i<=(b);i++)
#define fordown(i,a,b) for(int i=(a);i>=(b);i--)
#define maxn 200005
#define maxm 100005
#define INF 1070000000
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template<class T> inline
void read(T& num)
{ num = 0;
bool f = true;
char ch = getchar();
while(ch < '0' || ch > '9')
{ if(ch == '-') f = false;
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{ num = num * 10 + ch - '0';
ch = getchar();
}
num = f ? num: -num;
}
int out[100];
template<class T> inline
void write(T x,char ch)
{ if (x==0)
{ putchar('0');
putchar(ch);
return;
}
if (x<0)
{ putchar('-');
x=-x;
}
int num=0;
while (x)
{ out[num++]=(x%10);
x=x/10;
}
fordown(i,num-1,0) putchar(out[i]+'0');
putchar(ch);
}
/*==================split line=================*/
int n,m,cnt,tot,Clock;
int num[maxn],siz[maxn],sonh[maxn],depth[maxn],top[maxn];
int sum[maxn*10],lson[maxn*10],rson[maxn*10];
int san[maxn];
int tree[maxn];
vector<int> g[maxn];
int fa[maxn];
int LCA(int x,int y);
int ask(int x,int y,int rank)
{ int a=x,b=y,c=LCA(x,y),d=fa[c];
a=tree[a],b=tree[b],c=tree[c],d=tree[d];
int l=1,r=cnt;
while(l<r)
{
int mid=(l+r)>>1;
int tmp=sum[lson[a]]+sum[lson[b]]-sum[lson[c]]-sum[lson[d]];
if(tmp>=rank)r=mid,a=lson[a],b=lson[b],c=lson[c],d=lson[d];
else rank-=tmp,l=mid+1,a=rson[a],b=rson[b],c=rson[c],d=rson[d];
}
return san[l];
}
void pushup(int rt)
{ sum[rt] = sum[lson[rt]] + sum[rson[rt]];
}
int build(int l,int r)
{ int now=++tot;
if(l==r) return now;
int mid=(l+r)>>1;
lson[now]=build(l,mid);
rson[now]=build(mid+1,r);
return now;
}
int updata(int rt, int pos, int L, int R)
{ int now = ++tot;
if (L == R)
{ sum[now] = sum[rt] + 1;
lson[now] = rson[now] = 0;
return now;
}
int m = (L + R) >> 1;
if (pos <= m)
{ lson[now] = updata(lson[rt], pos, L, m);
rson[now] = rson[rt];
}
else
{ rson[now] = updata(rson[rt], pos, m+ 1, R);
lson[now] = lson[rt];
}
pushup(now);
return now;
}
void mark(int node,int topn)
{ top[node]=topn;
if (sonh[node]!=0) mark(sonh[node],topn);
for(int i=0; i<g[node].size(); i++)
{ int u=g[node][i];
if (u!=fa[node] && u!=sonh[node])
mark(u,u);
}
}
int LCA(int x,int y)
{ if(x==y) return x;
while(top[x]!=top[y])
{ if(depth[top[x]]<depth[top[y]])
swap(x,y);
x=top[x];
x=fa[x];
}
if(depth[x]<depth[y]) swap(x,y);
return y;
}
int dfs(int x,int fath)
{ fa[x]=fath;
tree[x]=updata(tree[fath],num[x],1,cnt);
depth[x]=depth[fath]+1;
int tmp=0;
int cmax=0,t=0;
for(int i=0; i<g[x].size(); i++)
{ int u=g[x][i];
if(u!=fath)
{ siz[u]=dfs(u,x);
tmp+=siz[u];
if(cmax<siz[u])
{ cmax=siz[u];
t=u;
}
}
}
sonh[x]=t;
return tmp+1;
}
int main()
{ read(n);
read(m);
forup(i,1,n) {read(num[i]),san[i]=num[i];}
sort(san+1,san+1+n);
cnt=std::unique(san+1,san+n+1)-san-1;
for(int i=1; i<=n; i++) num[i]=std::lower_bound(san+1,san+cnt+1,num[i])-san;
forup(i,1,n-1)
{ int x,y;
read(x);
read(y);
g[x].pb(y);
g[y].pb(x);
}
depth[1]=1;
tree[0]=build(1,cnt);
siz[1]=dfs(1,0);
mark(1,1);
int last=0;
while(m--)
{ int x,y,rank;
read(x),read(y),read(rank);
x^=last;
last=ask(x,y,rank);
printf("%d",last);
if (m) puts("");
}
return 0;
}