n<=100000的点权树,有m<=100000个询问,每次问两个点间的第k小点权,保证有解,强制在线。

主席上树啦!类似于之前的序列不带修改询问的前缀表示法,现在只要把前缀当成某点到根的信息即可。然后比如要问x点和y点,z为lca(x,y),w为z的爸爸,那么x,y,z,w四棵线段树一起跑即可。

 #include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
//#include<iostream>
using namespace std; int n,m;
#define maxn 100011
#define maxm 2000011
struct SMT
{
struct Node
{
int son[];
int cnt;
}a[maxm];
int size,n;
void clear(int m) {n=m;size=;a[].cnt=;}
void build(int pre,int &rt,int L,int R,int num)
{
rt=++size;
a[rt].cnt=a[pre].cnt+;
if (L==R) {a[rt].son[]=a[rt].son[]=;return;}
const int mid=(L+R)>>;
if (num<=mid) build(a[pre].son[],a[rt].son[],L,mid,num),a[rt].son[]=a[pre].son[];
else build(a[pre].son[],a[rt].son[],mid+,R,num),a[rt].son[]=a[pre].son[];
}
void build(int pre,int &rt,int num) {build(pre,rt,,n,num);}
// void test(int x,int L,int R)
// {
// const int mid=(L+R)>>1;
// if (a[x].son[0]) test(a[x].son[0],L,mid);
//// cout<<L<<' '<<R<<' '<<a[x].cnt<<endl;
// if (a[x].son[1]) test(a[x].son[1],mid+1,R);
// }
// void test(int x) {test(x,1,n);}
}smt; struct Edge{int to,next;}edge[maxn<<];int first[maxn],le=;
void in(int x,int y) {Edge &e=edge[le];e.to=y;e.next=first[x];first[x]=le++;}
void insert(int x,int y) {in(x,y);in(y,x);} int a[maxn],b[maxn],lb;
int fa[maxn][],dep[maxn],rt[maxn];
void dfs(int x,int f)
{
fa[x][]=f;dep[x]=dep[f]+;
for (int j=;j<=;j++)
fa[x][j]=fa[fa[x][j-]][j-];
smt.build(rt[f],rt[x],a[x]);
for (int i=first[x];i;i=edge[i].next)
{
const Edge &e=edge[i];if (e.to==f) continue;
dfs(e.to,x);
}
}
void pre() {dfs(,);} int lca(int x,int y)
{
if (dep[x]<dep[y]) {int t=x;x=y;y=t;}
for (int i=;i>=;i--) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if (x==y) return x;
for (int i=;i>=;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][];
} int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
lb=n;sort(b+,b++lb);lb=unique(b+,b++lb)-b-;
for (int i=;i<=n;i++) a[i]=lower_bound(b+,b++lb,a[i])-b; smt.clear(lb);
for (int i=,x,y;i<n;i++)
{
scanf("%d%d",&x,&y);
insert(x,y);
}
pre();
// for (int i=1;i<=n;i++) smt.test(rt[i]),cout<<endl;
int last=;
for (int i=,x,y,K;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&K);
x^=last;
int z=lca(x,y),w=fa[z][],L=,R=lb,tmp;
// cout<<x<<' '<<y<<' '<<z<<' '<<w<<endl;
x=rt[x];y=rt[y];z=rt[z];w=rt[w];
while (L<R)
{
if ((tmp=smt.a[smt.a[x].son[]].cnt+smt.a[smt.a[y].son[]].cnt
-smt.a[smt.a[z].son[]].cnt-smt.a[smt.a[w].son[]].cnt)>=K)
x=smt.a[x].son[],y=smt.a[y].son[],z=smt.a[z].son[],w=smt.a[w].son[],R=(L+R)>>;
else x=smt.a[x].son[],y=smt.a[y].son[],z=smt.a[z].son[],w=smt.a[w].son[],K-=tmp,L=((L+R)>>)+;
// cout<<tmp<<' '<<K<<endl;
}
printf("%d",(last=b[L]));
if (i<m) puts("");
}
return ;
}
05-11 19:43