• [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
    " , loc[query(root[dfn[u] + size[u] - 1] , root[dfn[u] - 1] , 1 , n , k)]);
            }
            
            return 0;
        
    }
  • 相关阅读:
    C++11的enum class & enum struct和enum
    c++11 中成员变量初始化的顺序
    c++11 lambda
    Java-NIO
    .Net之路(十五)图解LoadRunner压力測试
    activiti入门3排他网关,并行网管,包括网关,事件网关
    [移动端]移动端上遇到的各种坑与相对解决方式
    《软件调试艺术》读后感四
    [C++设计模式] command 命令模式
    iOS学习笔记23-音效与音乐
  • 原文地址:https://www.cnblogs.com/evenbao/p/9975734.html
Copyright © 2020-2023  润新知