bzoj 1803(主席树)

1803: Spoj1487 Query on a tree III

Time Limit: 1 Sec   Memory Limit: 64 MB
Submit: 419   Solved: 184
[ Submit][ Status][ Discuss]

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


解题思路:首先dfs求出dfs序列,然后就将树的数据化到序列上了,然后在序列上找K大,明显主席树。然而输出有点奇怪,输出的是值所对应得点,那只要多储存一个值,

就是到第i棵线段树,保存更改的最小面的那个值所对应的最后面的对应得点。


#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define MAX 200009
#define u 18

using namespace std;

int to[1 * MAX], next[1 * MAX], head[1 * MAX], a[MAX], c[MAX];
int n, m, k, dfn[MAX * 1], tree[u * MAX], child[u * MAX][2], size[u * MAX];
int tot = 0, DfsClock = 0, sum = 0, first[MAX * 1], last[1 * MAX], num = 0;

inline void add (int x, int y)
{
 to[++tot] = y;
 next[tot] = head[x];
 head[x] = tot;
}

void dfs (int x, int fa)
{
 dfn[first[x] = ++DfsClock] = x;
 for (int i = head[x]; i; i = next[i])
  if (to[i] != fa)
   dfs (to[i], x);
 dfn[last[x] = ++DfsClock] = x;
}

inline int add (int l, int r, int pos, int root)
{
 int New = ++sum, mid = (l + r) >> 1;
  size[New] = size[root] + 1;
  if (l == r)
    return New;
  if (pos <= mid)
  child[New][0] = add (l, mid, pos, child[root][0]), child[New][1] = child[root][1];
 else
  child[New][0] = child[root][0], child[New][1] = add (mid + 1, r, pos, child[root][1]);
 return New;
}

struct wbysr
{
 int value, id;
}e[MAX];

bool cmp (wbysr a1, wbysr a2)
{
 return a1.value < a2.value;
}

int main()
{
 scanf ("%d", &n);
 rep (i, 1, n)
  scanf ("%d", &a[i]), e[i].value = a[i], e[i].id = i;
 sort (e + 1, e + 1 + n, cmp);
 e[0].value = e[1].value - 90;
 rep (i, 1, n)
  if (e[i].value != e[i-1].value)
   c[++num] = e[i].value;
 rep (i, 1, n - 1)
 {
  int a1, a2;
  scanf ("%d%d", &a1, &a2);
  add (a1, a2);
  add (a2, a1);
 }
 dfs (1,0);
 tree[0] = 0;
 size[0] = 0;
 rep (i, 1, DfsClock)
  tree[i] = add (1, num, lower_bound (c + 1, c + 1 + num, a[dfn[i]]) - c, tree[i - 1]);


 scanf ("%d", &m);
 while (m--)
 {
  int x;
  scanf ("%d%d", &x, &k);
  k *= 2;
  int t0 = tree[first[x] - 1], t1 = tree[last[x]];
  int l = 1, r = num;
  while (l <= r)
  {
   int now = size[child[t1][0]] - size[child[t0][0]];
   int mid = (l + r) >> 1;
      if (k <= now)
    t0 = child[t0][0], t1 = child[t1][0], r = mid;
   else
    t0 = child[t0][1], t1 = child[t1][1], k -= now, l = mid + 1;
  }
  printf ("%d\n", e[r].id);
 }
 return 0;
}

你可能感兴趣的:(bzoj 1803(主席树))