题意
给定一个有n个结点的树,在线询问两个点之间路径上第k大的点的点权是多少。
分析
其实刚开始看到这道题的想法是树链剖分出log条链在同时在可持久化线段树上查询第k大。但是这样写起来并不优雅而且很难写。
然后考虑每次其实相当于取出两条点到某个祖先的链找第k大,所以这里的可持久化线段树可以不基于dfs序,而是直接用父亲结点的线段树。
然后这样就只需要求一个lca,然后开始的时候建一棵可持久化线段树即可。
code
//2018年06月09日 星期六 10时16分17秒
#include<bits/stdc++.h>
#define M 100005
using namespace std;
void read(int &x){
x=0; char c=getchar();
for (;c<48;c=getchar());
for (;c>47;c=getchar())x=(x<<1)+(x<<3)+(c^48);
}
struct ed{
int x,nx;
}e[M<<1];
int a[M],b[M],rt[M],fa[M],top[M],son[M],de[M],nx[M],ecnt=1,cnt[M];
void add(int x,int y){
e[ecnt]=(ed){y,nx[x]};
nx[x]=ecnt++;
}
int ch(int l,int r,int x){
int mid;
for (;l<=r;){
mid=(l+r)>>1;
if (b[mid]==x)return mid;
if (b[mid]<x)l=mid+1;
else r=mid-1;
}
}
struct Tree{
int tot,f[M*30],rs[M*30],ls[M*30];
void build(int l,int r,int &p){
p=++tot;
if (l==r)return;
int mid=(l+r)>>1;
build(l,mid,ls[p]);
build(mid+1,r,rs[p]);
}
void build(int l,int r,int x,int lp,int &p){
p=++tot;
ls[p]=ls[lp];
rs[p]=rs[lp];
f[p]=f[lp]+1;
if (l==r){
return;
}
int mid=(l+r)>>1;
if (x<=mid)build(l,mid,x,ls[lp],ls[p]);
else build(mid+1,r,x,rs[lp],rs[p]);
}
int qu(int l,int r,int k,int p1,int p2,int p3,int p4){
if (l==r)return l;
int sum=(f[ls[p1]]+f[ls[p2]]-f[ls[p3]]-f[ls[p4]]),mid=(l+r)>>1;
if (sum>=k)return qu(l,mid,k,ls[p1],ls[p2],ls[p3],ls[p4]);
else return qu(mid+1,r,k-sum,rs[p1],rs[p2],rs[p3],rs[p4]);
}
void pt(int l,int r,int p){
if (l==r){
printf("%d ",f[p]);
return ;
}
int mid=(l+r)>>1;
pt(l,mid,ls[p]);
pt(mid+1,r,rs[p]);
}
}T;
int tot;
void dfs1(int f,int x){
fa[x]=f; cnt[x]=1; de[x]=de[f]+1; son[x]=0;
for (int i=nx[x];i;i=e[i].nx)if (e[i].x!=f){
dfs1(x,e[i].x);
cnt[x]+=cnt[e[i].x];
if (cnt[e[i].x]>cnt[son[x]])son[x]=e[i].x;
}
}
void dfs2(int f,int x){
top[x]=f;
T.build(1,tot,a[x],rt[fa[x]],rt[x]);
if (son[x])dfs2(f,son[x]);
for (int i=nx[x];i;i=e[i].nx)if(e[i].x!=fa[x]&&e[i].x!=son[x]){
dfs2(e[i].x,e[i].x);
}
}
int lca(int x,int y){
for (;top[x]!=top[y];){
if (de[top[x]]>de[top[y]])x=fa[top[x]];
else y=fa[top[y]];
}
if (de[x]<de[y])return x;
return y;
}
int qu(int x,int y,int k){
int Lca=lca(x,y);
return T.qu(1,tot,k,rt[x],rt[y],rt[Lca],rt[fa[Lca]]);
}
int main(){
// freopen("1.in","r",stdin);
int n,m,i,x,y,res=0,k;
read(n); read(m);
for (i=1;i<=n;i++)read(a[i]),b[i]=a[i];
sort(b+1,b+n+1);
tot=unique(b+1,b+n+1)-b-1;
for (i=1;i<=n;i++)a[i]=ch(1,tot,a[i]);
for (i=1;i<n;i++){
read(x); read(y);
add(x,y); add(y,x);
}
T.build(1,tot,rt[0]);
dfs1(0,1);
dfs2(1,1);
// for (i=1;i<=n;i++)printf("------%d-------\n",i),T.pt(1,tot,rt[i]),printf("\n");
for (;m--;){
read(x); read(y); read(k);
x^=res;
res=b[qu(x,y,k)];
printf("%d",res);
if (m)puts("");
}
return 0;
}
其实是很裸的题?qwq我太弱了