[xdoj1216]子树第k小(dfs序+主席树)

时间:2023-03-09 05:57:12
[xdoj1216]子树第k小(dfs序+主席树)

解题关键:dfs序将树映射到区间,然后主席树求区间第k小,为模板题。

 #pragma comment(linker, "/STACK:1024000000,1024000000") `
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath>
#include<vector>
typedef long long ll;
using namespace std;
const int maxn=1e5+;
int head[maxn],in[maxn],out[maxn],cnt,num;
int b[maxn],va[maxn];
int n,m;
struct Edge{
int to,nxt;
}e[maxn<<];
int root[maxn];
struct node{
int l,r,sum;
}p[maxn*]; inline int read(){
char k=;char ls;ls=getchar();for(;ls<''||ls>'';k=ls,ls=getchar());
int x=;for(;ls>=''&&ls<='';ls=getchar())x=(x<<)+(x<<)+ls-'';
if(k=='-')x=-x;return x;
} void add_edge(int u,int v){
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
} void dfs(int u,int fa){
num++;
b[num]=va[u];
in[u]=num;
for(int i=head[u];i!=-;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
dfs(v,u);
}
out[u]=num;
} int build(int l,int r){
int rt=++cnt;
p[rt].sum=;
p[rt].l=p[rt].r=;
if(l==r) return rt;
int mid=(l+r)>>;
p[rt].l=build(l,mid);
p[rt].r=build(mid+,r);
return rt;
} int update(int l,int r,int c,int k){
int nc=++cnt;
p[nc]=p[c];
p[nc].sum++;
int mid=(l+r)>>;
if(l==r) return nc;
if(mid>=k) p[nc].l=update(l,mid,p[c].l,k);
else p[nc].r=update(mid+,r,p[c].r,k);
return nc;
} int query(int l,int r,int x,int y,int k){
if(l==r) return l;
int mid=(l+r)>>;
int sum=p[p[y].l].sum-p[p[x].l].sum;
if(sum>=k) return query(l,mid,p[x].l,p[y].l,k);
else return query(mid+,r,p[x].r,p[y].r,k-sum);
}
vector<int>v;
int getid(int x){
return int(lower_bound(v.begin(),v.end(),x)-v.begin())+;
} int main(){
while(scanf("%d",&n)!=EOF){
v.clear();
memset(head,-,sizeof head);
cnt=;
num=;
for(int i=;i<=n;i++) va[i]=read();
for(int i=;i<n-;i++){
int t1,t2;
t1=read();
t2=read();
add_edge(t1,t2);
add_edge(t2,t1);
}
dfs(,-);
for(int i=;i<=n;i++) v.push_back(b[i]);
sort(v.begin(),v.end());
v.erase(unique(v.begin(), v.end()),v.end());
root[]=build(,n);
for(int i=;i<=n;i++) root[i]=update(,n,root[i-],getid(b[i]));
int c,d;
m=read();
for(int i=;i<m;i++){
c=read();
d=read();
int ans=query(,n,root[in[c]-],root[out[c]],d);
printf("%d\n",v[ans-]);
}
}
return ;
}