【bzoj1803】Spoj1487 Query on a tree III DFS序+主席树

题目描述

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.

输入

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)

输出

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.

样例输入

5 1 3 5 2 7 1 2 2 3 1 4 3 5 4 2 3 4 1 3 2 3 2

样例输出

5 4 5 5


题目大意

给出一棵以1为根的树,每个点有一个点权。多次询问每个点为根的子树中权值第k小的点是哪个

题解

DFS序+主席树

我也不知道为什么k-th largest number是第k小的意思。反正第k小既能解释样例又能A题。

维护一个DFS序,然后子树就转化为一段连续的区间,我们要求区间第k小。

直接裸上主席树即可。

#include <cstdio> 
#include <algorithm> 
#define N 100010 
using namespace std; 
int w[N] , s[N] , r[N] , head[N] , to[N << 1] , nxt[N << 1] , cnt , pos[N] , v[N] , last[N] , tot , root[N] , ls[N * 18] , rs[N * 18] , si[N * 18] , num; 
void add(int x , int y) 
{ 
    to[++cnt] = y , nxt[cnt] = head[x] , head[x] = cnt; 
} 
void dfs(int x , int fa) 
{ 
    int i; 
    pos[x] = ++tot , v[tot] = w[x]; 
    for(i = head[x] ; i ; i = nxt[i]) if(to[i] != fa) dfs(to[i] , x); 
    last[x] = tot; 
} 
void ins(int p , int l , int r , int x , int &y) 
{ 
    y = ++num , si[y] = si[x] + 1; 
    if(l == r) return; 
    int mid = (l + r) >> 1; 
    if(p <= mid) rs[y] = rs[x] , ins(p , l , mid , ls[x] , ls[y]); 
    else ls[y] = ls[x] , ins(p , mid + 1 , r , rs[x] , rs[y]); 
} 
int query(int k , int l , int r , int x , int y) 
{ 
    if(l == r) return l; 
    int mid = (l + r) >> 1; 
    if(k <= si[ls[y]] - si[ls[x]]) return query(k , l , mid , ls[x] , ls[y]); 
    else return query(k - si[ls[y]] + si[ls[x]] , mid + 1 , r , rs[x] , rs[y]); 
} 
int main() 
{ 
    int n , m , i , x , y; 
    scanf("%d" , &n); 
    for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &w[i]) , s[i] = w[i]; 
    sort(s + 1 , s + n + 1); 
    for(i = 1 ; i <= n ; i ++ ) w[i] = lower_bound(s + 1 , s + n + 1 , w[i]) - s , r[w[i]] = i; 
    for(i = 1 ; i < n ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , add(y , x); 
    dfs(1 , 0); 
    for(i = 1 ; i <= n ; i ++ ) ins(v[i] , 1 , n , root[i - 1] , root[i]); 
    scanf("%d" , &m); 
    while(m -- ) scanf("%d%d" , &x , &y) , printf("%d\n" , r[query(y , 1 , n , root[pos[x] - 1] , root[last[x]])]); 
    return 0; 
}

 

posted @ 2017-06-03 21:01  GXZlegend  阅读(323)  评论(0编辑  收藏  举报