1. 程式人生 > >SPOJ1487 Query on a tree III

SPOJ1487 Query on a tree III

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大嗎?

樹套樹/主席樹亂搞,但是卡空間,就用主席樹了。

#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;
}