大致题意: 求子树第(k)大。
(SB)题
显然求出原序列的(dfs)序列,然后子树就变成了一个区间。
动态第(k)大可以用树套树(分块:?),静态第(k)大直接主席树就好了,显然是裸题。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define LN 25
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
using namespace std;
int n,a[N+5],g[N+5],ee,lnk[N+5],d,dI[N+5],dO[N+5],f[N+5];struct edge {int to,nxt;}e[N<<1];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C==E&&(clear(),0),*C++=c)
#define D isdigit(c=tc())
int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI,C=FO,E=FO+FS;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=(x<<3)+(x<<1)+(c&15),D);}
Tp I void writeln(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);pc('
');}
I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
}F;
class ChairmanTree
{
private:
#define LT l,mid,O[x].S[0],O[y].S[0]
#define RT mid+1,r,O[x].S[1],O[y].S[1]
int Nt,Rt[N+5];struct node {int Sz,S[2];}O[N*LN+5];
I void Ins(CI p,CI l,CI r,int& x,CI y)//插入一个数
{
if(++(O[x=++Nt]=O[y]).Sz,l==r) return;int mid=l+r>>1;
p<=mid?Ins(p,LT):Ins(p,RT);
}
I int Qry(CI rk,CI l,CI r,CI x,CI y)//询问
{
if(l==r) return g[l];int mid=l+r>>1,t=O[O[y].S[0]].Sz-O[O[x].S[0]].Sz;
return rk<=t?Qry(rk,LT):Qry(rk-t,RT);
}
public:
I void Ins(CI v,CI x) {Ins(x,1,n,Rt[v],Rt[v-1]);}
I int Qry(CI x,CI y) {return Qry(y,1,n,Rt[dI[x]-1],Rt[dO[x]]);}
}C;
I void dfs(CI x)//求出dfs序列
{
f[dI[x]=++d]=x;for(RI i=lnk[x];i;i=e[i].nxt) !dI[e[i].to]&&(dfs(e[i].to),0);dO[x]=d;
}
I bool cmp(CI x,CI y) {return a[x]<a[y];}
int main()
{
RI Qt,i,x,y;for(F.read(n),i=1;i<=n;++i) F.read(a[i]),g[i]=i;
for(sort(g+1,g+n+1,cmp),i=1;i<=n;++i) a[g[i]]=i;//离散化(因为保证数各不同)
for(i=1;i^n;++i) F.read(x),F.read(y),add(x,y),add(y,x);dfs(1);//连边dfs
for(i=1;i<=n;++i) C.Ins(i,a[f[i]]);//插入元素
F.read(Qt);W(Qt--) F.read(x),F.read(y),F.writeln(C.Qry(x,y));//处理询问
return F.clear(),0;
}