[BZOJ 1803] Query on a tree III

[题目链接]

          https://www.lydsy.com/JudgeOnline/problem.php?id=1803

[算法]

        首先 , 一棵子树的DFS序必然为连续的一段

        通过这个性质 , 我们将一个树上的问题转化为了一个序列上的问题

        可持久化线段树可以解决该问题 , 不再赘述

        时间复杂度 : O(MlogN)

[代码]

        

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;

struct edge
{
        int to , nxt;
} e[MAXN << 2];

int tot , n , m , timer , idx;
int root[MAXN] , dfn[MAXN] , size[MAXN] , head[MAXN] , a[MAXN] , order[MAXN] , tmp[MAXN] , loc[MAXN] , lson[MAXN * 40] , rson[MAXN * 40] , sum[MAXN * 40];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
inline void addedge(int x , int y)
{
        ++tot;
        e[tot] = (edge){y , head[x]};
        head[x] = tot;
}
inline bool cmp(int x , int y)
{
        return dfn[x] < dfn[y];
}
inline void dfs(int u , int fa)
{
        dfn[u] = ++timer;
      size[u] = 1;
      for (int i = head[u]; i; i = e[i].nxt)
      {
              int v = e[i].to;
              if (v == fa) continue;
              dfs(v , u);
              size[u] += size[v];
        }
}
inline void build(int &k , int l , int r)
{
        k = ++idx;
        if (l == r) return;
        int mid = (l + r) >> 1;
        build(lson[k] , l , mid);
        build(rson[k] , mid + 1 , r);
}
inline void modify(int &k , int old , int l , int r , int pos , int value)
{
        k = ++idx;
        lson[k] = lson[old] , rson[k] = rson[old];
        sum[k] = sum[old] + value;
        if (l == r) return;
        int mid = (l + r) >> 1;
        if (mid >= pos) modify(lson[k] , lson[k] , l , mid , pos , value);
        else modify(rson[k] , rson[k] , mid + 1 , r , pos , value);        
}
inline int query(int rt1 , int rt2 , int l , int r , int k)
{
        if (l == r)    return l;
        int mid = (l + r) >> 1;
        if (sum[lson[rt1]] - sum[lson[rt2]] >= k) return query(lson[rt1] , lson[rt2] , l , mid , k);
        else return query(rson[rt1] , rson[rt2] , mid + 1 , r , k - (sum[lson[rt1]] - sum[lson[rt2]]));
}

int main()
{
        
        read(n); 
        for (int i = 1; i <= n; i++) 
        {
                read(a[i]);
                tmp[i] = a[i];
        }
        sort(tmp + 1 , tmp + n + 1);
        for (int i = 1; i <= n; i++)
        {
                int l = 1 , r = n , pos;
                while (l <= r)
                {
                        int mid = (l + r) >> 1;
                        if (tmp[mid] >= a[i])
                        {
                                pos = mid;
                                r = mid - 1;
                        } else l = mid + 1;
                }
                a[i] = pos;
                loc[pos] = i;
        }
        for (int i = 1; i < n; i++)
        {
                int x , y;
                read(x); read(y);
                addedge(x , y);
                addedge(y , x);        
        }
        dfs(1 , 0);
        for (int i = 1; i <= n; i++) order[i] = i;
        sort(order + 1 , order + n + 1 , cmp);
        build(root[0] , 1 , n);
        for (int i = 1; i <= n; i++)
                modify(root[i] , root[i - 1] , 1 , n , a[order[i]] , 1);
        read(m);
        while (m--)
        {
                int u , k;
                read(u); read(k);
                printf("%d\n" , loc[query(root[dfn[u] + size[u] - 1] , root[dfn[u] - 1] , 1 , n , k)]);
        }
        
        return 0;
    
}

 

posted @ 2018-11-17 21:34  evenbao  阅读(157)  评论(0编辑  收藏  举报