传送门 http://www.lydsy.com/JudgeOnline/problem.php?id=2588
Solution
读入玩得太骚玩挂了QwQ
每个点维护它到根的这条链上的所有权值
使用值域线段树,可以用类似于可持久化的方法
这样查询就可以用u,v,lca(u,v),father[lac(u,v)]四个点对应的值域线段树相减得到解
#include<stdio.h>
#include<algorithm>
#define cint const int &
#define l(k) t[k].lson
#define r(k) t[k].rson
#define N 100005
using namespace std;
typedef long long ll;
int tot,s[N],c[N],dep[N],f[N][17],n,m,rt[N],aim;
ll a[N],d[N],ans;
struct edge{int v,n;}e[N<<1];
inline void push(cint u,cint v){e[++tot]=(edge){v,s[u]};s[u]=tot;}
struct node{int sum,lson,rson;}t[N*20];
inline bool cmp(cint x,cint y){return a[x]<a[y];}
void ins(int &k,cint lk,cint l,cint r)
{
if (!k) k=++tot;
if (l==r){t[k].sum++;return;}
int mid=l+r>>1;
if (aim<=mid){ins(l(k),l(lk),l,mid);r(k)=r(lk);}
else{ins(r(k),r(lk),mid+1,r);l(k)=l(lk);}
t[k].sum=t[l(k)].sum+t[r(k)].sum;
}
void find(cint k1,cint k2,cint k3,cint k4,cint l,cint r,cint aim)
{
if (l==r){ans=d[l];return;}
int mid=l+r>>1,lsum=t[l(k1)].sum+t[l(k2)].sum-t[l(k3)].sum-t[l(k4)].sum;
if (aim<=lsum) find(l(k1),l(k2),l(k3),l(k4),l,mid,aim);
else find(r(k1),r(k2),r(k3),r(k4),mid+1,r,aim-lsum);
}
void dfs(cint k,cint fa)
{
dep[k]=dep[f[k][0]=fa]+1;
for (int i=1;(1<<i)<dep[k];i++) f[k][i]=f[f[k][i-1]][i-1];
aim=a[k];ins(rt[k],rt[fa],1,n);
for (int i=s[k];i;i=e[i].n) if (e[i].v!=fa) dfs(e[i].v,k);
}
inline int lca(int u,int v)
{
if (dep[u]<dep[v]) swap(u,v);
for (int i=16;0<=i;i--) if ((1<<i)+dep[v]<=dep[u]) u=f[u][i];
if (u==v) return u;
for (int i=16;0<=i;i--) if (f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
return f[u][0];
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%lld",a+i);
for (int i=1;i<=n;i++) c[i]=i;
sort(c+1,c+n+1,cmp);
for (int i=1;i<=n;i++) d[i]=a[c[i]],a[c[i]]=i;
for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),push(u,v),push(v,u);
dfs(1,0);
for (int u,v,k,ac,i=1;i<=m;i++)
{
ll ui;
scanf("%lld%d%d",&ui,&v,&k);u=ui^ans;
ac=lca(u,v);
find(rt[u],rt[v],rt[ac],rt[f[ac][0]],1,n,k);
printf("%lld",ans);
if (i<m) printf("\n");
}
}