Description
You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node whose label is k-th largest in the subtree of the node x. Assume no two nodes have the same labels.
Input
The first line contains one integer n (1 <= n <= 10^5). The next line contains n integers li (0 <= li <= 109) which denotes the label of the i-th node. Each line of the following n - 1 lines contains two integers u, v. They denote there is an edge between node u and node v. Node 1 is the root of the tree. The next line contains one integer m (1 <= m <= 10^4) which denotes the number of the queries. Each line of the next m contains two integers x, k. (k <= the total node number in the subtree of x)
Output
For each query (x, k), output the index of the node whose label is the k-th largest in the subtree of the node x.
Sample Input
5
1 3 5 2 7
1 2
2 3
1 4
3 5
4
2 3
4 1
3 2
3 2
Sample Output
5 4 5 5
题目大意:给你一颗以1为根的树,每个点权值各不相同,每次查询以x为根的子树中权值第k大的节点标号。
之前看过,一眼看上去水题,发现操作不来就没管这道题。
今天刚好切一道树剖题用到dfs序这个东西,那么不就是在dfs序上求区间第k大吗?
树套树/主席树乱搞,但是卡空间,就用主席树了。
补:今天早上琢磨树的操作时,又想到可以用dsu水过去。。
#include<bits/stdc++.h>
using namespace std;
#define show_memory(x) cout<<sizeof(x)/(1024*1024.0)<<"\n";
const int Maxn=100005;
struct Edge{
int cnt,h[Maxn],to[Maxn*2],next[Maxn*2];
inline void add(int x,int y){
next[++cnt]=h[x];to[cnt]=y;h[x]=cnt;
}
}e;
#define to e.to[p]
int n,m,v[Maxn];
int cnt,p[Maxn],fir[Maxn],sec[Maxn];
map<int,int>fp;
void dfs(int x,int fa){
p[fir[x]=++cnt]=x;
for(int p=e.h[x];p;p=e.next[p])
if(to^fa)dfs(to,x);
sec[x]=cnt;
}
struct SegMent{
struct tree{
int ls,rs,siz;
}t[Maxn*40];
int tot,root[Maxn];
inline void insert(int &x,int o,int l,int r,int val){
if(r<val||l>val)return ;
t[x=++tot]=t[o];
++t[x].siz;
if(l==r)return ;
int mid=l+r>>1;
insert(t[x].ls,t[o].ls,l,mid,val),insert(t[x].rs,t[o].rs,mid+1,r,val);
}
inline int query(int R,int L,int l,int r,int kth){
if(l==r)return fp[l];
int size=t[t[R].ls].siz-t[t[L].ls].siz;
int mid=l+r>>1;
if(size>=kth)return query(t[R].ls,t[L].ls,l,mid,kth);
else return query(t[R].rs,t[L].rs,mid+1,r,kth-size);
}
}seg;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&v[i]);
fp[v[i]]=i;
}
for(int i=1;i<n;++i){
int x,y;scanf("%d%d",&x,&y);
e.add(x,y),e.add(y,x);
}
dfs(1,0);
for(int i=1;i<=n;++i)seg.insert(seg.root[i],seg.root[i-1],0,1e9,v[p[i]]);
scanf("%d",&m);
for(int i=1;i<=m;++i){
int x,k;scanf("%d%d",&x,&k);
printf("%d\n",seg.query(seg.root[sec[x]],seg.root[fir[x]-1],0,1e9,k));
}
// show_memory(seg);
return 0;
}