# BZOJ 2588: Spoj 10628. Count on a tree | 树上主席树

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 200010
using namespace std;
struct node {int lc,rc,sum;}t[N*20];
struct edge {int nxt,v;}e[2*N];
{
}
void Insert(int x,int &y,int l,int r,int k)
{
t[y=++pcnt]=t[x];t[y].sum++;
if (l==r) return ;
int mid=l+r>>1;
if (k<=mid) Insert(t[x].lc,t[y].lc,l,mid,k);
else Insert(t[x].rc,t[y].rc,mid+1,r,k);
}
void dfs(int u)
{
deep[u]=deep[anc[u][0]]+1;
Insert(root[anc[u][0]],root[u],1,lim,w[u]);
if (e[i].v!=anc[u][0])
anc[v=e[i].v][0]=u,dfs(v);
}
int lca(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
for (int i=20;i>=0;i--)
if (deep[anc[x][i]]>=deep[y])
x=anc[x][i];
if (x==y) return x;
for (int i=20;i>=0;i--)
if (anc[x][i]!=anc[y][i])
x=anc[x][i],y=anc[y][i];
return anc[x][0];
}
int query(int u,int v,int k)
{
int GGfa=lca(u,v),tmp[4]={root[u],root[v],root[GGfa],root[anc[GGfa][0]]},val,l=1,r=lim,mid;
while (l<r)
{
mid=l+r>>1;
val=t[t[tmp[0]].lc].sum+t[t[tmp[1]].lc].sum-t[t[tmp[2]].lc].sum-t[t[tmp[3]].lc].sum;
if (k<=val)
{
r=mid;
for (int i=0;i<4;i++)
tmp[i]=t[tmp[i]].lc;
}
else
{
l=mid+1;k-=val;
for (int i=0;i<4;i++)
tmp[i]=t[tmp[i]].rc;
}
}
return b[l];
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",w+i),b[i]=w[i];
sort(b+1,b+n+1);
lim=unique(b+1,b+1+n)-b-1;
for (int i=1;i<=n;i++)
w[i]=lower_bound(b+1,b+1+lim,w[i])-b;
for (int i=1,u,v;i<n;i++)
dfs(1);
for (int j=1;j<=20;j++)
for (int i=1;i<=n;i++)
anc[i][j]=anc[anc[i][j-1]][j-1];
for (int i=1,u,v,k;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&k);
printf("%d",lastans=query(u^lastans,v,k));
if (i<m) printf("\n");
}
return 0;
}

posted @ 2017-12-31 19:28  MSPqwq  阅读(122)  评论(0编辑  收藏  举报