• SPOJ 10628. Count on a tree (树上第k大,LCA+主席树)


    10628. Count on a tree

    Problem code: COT

     

    You are given a tree with N nodes.The tree nodes are numbered from 1 to N.Each node has an integer weight.

    We will ask you to perform the following operation:

    • u v k : ask for the kth minimum weight on the path from node u to node v

    Input

    In the first line there are two integers N and M.(N,M<=100000)

    In the second line there are N integers.The ith integer denotes the weight of the ith node.

    In the next N-1 lines,each line contains two integers u v,which describes an edge (u,v).

    In the next M lines,each line contains three integers u v k,which means an operation asking for the kth minimum weight on the path from node u to node v.

    Output

    For each operation,print its result.

    Example

    Input:
    8 5
    8 5
    105 2 9 3 8 5 7 7
    1 2        
    1 3
    1 4
    3 5
    3 6
    3 7
    4 8
    2 5 1
    2 5 2
    2 5 3
    2 5 4
    7 8 2 
    Output:
    2
    8
    9
    105

    在树上建立主席树。

    然后求LCA

      1 /* ***********************************************
      2 Author        :kuangbin
      3 Created Time  :2013-9-5 10:31:57
      4 File Name     :F:2013ACM练习专题学习主席树SPOJ_COT.cpp
      5 ************************************************ */
      6 
      7 #include <stdio.h>
      8 #include <string.h>
      9 #include <iostream>
     10 #include <algorithm>
     11 #include <vector>
     12 #include <queue>
     13 #include <set>
     14 #include <map>
     15 #include <string>
     16 #include <math.h>
     17 #include <stdlib.h>
     18 #include <time.h>
     19 using namespace std;
     20 
     21 //主席树部分 *****************8
     22 const int MAXN = 200010;
     23 const int M = MAXN * 40;
     24 int n,q,m,TOT;
     25 int a[MAXN], t[MAXN];
     26 int T[M], lson[M], rson[M], c[M];
     27 
     28 void Init_hash()
     29 {
     30     for(int i = 1; i <= n;i++)
     31         t[i] = a[i];
     32     sort(t+1,t+1+n);
     33     m = unique(t+1,t+n+1)-t-1;
     34 }
     35 int build(int l,int r)
     36 {
     37     int root = TOT++;
     38     c[root] = 0;
     39     if(l != r)
     40     {
     41         int mid = (l+r)>>1;
     42         lson[root] = build(l,mid);
     43         rson[root] = build(mid+1,r);
     44     }
     45     return root;
     46 }
     47 int hash(int x)
     48 {
     49     return lower_bound(t+1,t+1+m,x) - t;
     50 }
     51 int update(int root,int pos,int val)
     52 {
     53     int newroot = TOT++, tmp = newroot;
     54     c[newroot] = c[root] + val;
     55     int l = 1, r = m;
     56     while( l < r)
     57     {
     58         int mid = (l+r)>>1;
     59         if(pos <= mid)
     60         {
     61             lson[newroot] = TOT++; rson[newroot] = rson[root];
     62             newroot = lson[newroot]; root = lson[root];
     63             r = mid;
     64         }
     65         else
     66         {
     67             rson[newroot] = TOT++; lson[newroot] = lson[root];
     68             newroot = rson[newroot]; root = rson[root];
     69             l = mid+1;
     70         }
     71         c[newroot] = c[root] + val;
     72     }
     73     return tmp;
     74 }
     75 int query(int left_root,int right_root,int LCA,int k)
     76 {
     77     int lca_root = T[LCA];
     78     int pos = hash(a[LCA]);
     79     int l = 1, r = m;
     80     while(l < r)
     81     {
     82         int mid = (l+r)>>1;
     83         int tmp = c[lson[left_root]] + c[lson[right_root]] - 2*c[lson[lca_root]] + (pos >= l && pos <= mid);
     84         if(tmp >= k)
     85         {
     86             left_root = lson[left_root];
     87             right_root = lson[right_root];
     88             lca_root = lson[lca_root];
     89             r = mid;
     90         }
     91         else
     92         {
     93             k -= tmp;
     94             left_root = rson[left_root];
     95             right_root = rson[right_root];
     96             lca_root = rson[lca_root];
     97             l = mid + 1;
     98         }
     99     }
    100     return l;
    101 }
    102 
    103 //LCA部分
    104 int rmq[2*MAXN];//rmq数组,就是欧拉序列对应的深度序列
    105 struct ST
    106 {
    107     int mm[2*MAXN];
    108     int dp[2*MAXN][20];//最小值对应的下标
    109     void init(int n)
    110     {
    111         mm[0] = -1;
    112         for(int i = 1;i <= n;i++)
    113         {
    114             mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
    115             dp[i][0] = i;
    116         }
    117         for(int j = 1; j <= mm[n];j++)
    118             for(int i = 1; i + (1<<j) - 1 <= n; i++)
    119                 dp[i][j] = rmq[dp[i][j-1]] < rmq[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
    120     }
    121     int query(int a,int b)//查询[a,b]之间最小值的下标
    122     {
    123         if(a > b)swap(a,b);
    124         int k = mm[b-a+1];
    125         return rmq[dp[a][k]] <= rmq[dp[b-(1<<k)+1][k]]?dp[a][k]:dp[b-(1<<k)+1][k];
    126     }
    127 };
    128 //边的结构体定义
    129 struct Edge
    130 {
    131     int to,next;
    132 };
    133 Edge edge[MAXN*2];
    134 int tot,head[MAXN];
    135 
    136 int F[MAXN*2];//欧拉序列,就是dfs遍历的顺序,长度为2*n-1,下标从1开始
    137 int P[MAXN];//P[i]表示点i在F中第一次出现的位置
    138 int cnt;
    139 
    140 ST st;
    141 void init()
    142 {
    143     tot = 0;
    144     memset(head,-1,sizeof(head));
    145 }
    146 void addedge(int u,int v)//加边,无向边需要加两次
    147 {
    148     edge[tot].to = v;
    149     edge[tot].next = head[u];
    150     head[u] = tot++;
    151 }
    152 void dfs(int u,int pre,int dep)
    153 {
    154     F[++cnt] = u;
    155     rmq[cnt] = dep;
    156     P[u] = cnt;
    157     for(int i = head[u];i != -1;i = edge[i].next)
    158     {
    159         int v = edge[i].to;
    160         if(v == pre)continue;
    161         dfs(v,u,dep+1);
    162         F[++cnt] = u;
    163         rmq[cnt] = dep;
    164     }
    165 }
    166 void LCA_init(int root,int node_num)//查询LCA前的初始化
    167 {
    168     cnt = 0;
    169     dfs(root,root,0);
    170     st.init(2*node_num-1);
    171 }
    172 int query_lca(int u,int v)//查询u,v的lca编号
    173 {
    174     return F[st.query(P[u],P[v])];
    175 }
    176 
    177 void dfs_build(int u,int pre)
    178 {
    179     int pos = hash(a[u]);
    180     T[u] = update(T[pre],pos,1);
    181     for(int i = head[u]; i != -1;i = edge[i].next)
    182     {
    183         int v = edge[i].to;
    184         if(v == pre)continue;
    185         dfs_build(v,u);
    186     }
    187 }
    188 int main()
    189 {
    190     //freopen("in.txt","r",stdin);
    191     //freopen("out.txt","w",stdout);
    192     while(scanf("%d%d",&n,&q) == 2)
    193     {
    194         for(int i = 1;i <= n;i++)
    195             scanf("%d",&a[i]);
    196         Init_hash();
    197         init();
    198         TOT = 0;
    199         int u,v;
    200         for(int i = 1;i < n;i++)
    201         {
    202             scanf("%d%d",&u,&v);
    203             addedge(u,v);
    204             addedge(v,u);
    205         }
    206         LCA_init(1,n);
    207         T[n+1] = build(1,m);
    208         dfs_build(1,n+1);
    209         int k;
    210         while(q--)
    211         {
    212             scanf("%d%d%d",&u,&v,&k);
    213             printf("%d
    ",t[query(T[u],T[v],query_lca(u,v),k)]);
    214         }
    215         return 0;
    216     }
    217     return 0;
    218 }
  • 相关阅读:
    cf1100 F. Ivan and Burgers
    cf 1033 D. Divisors
    LeetCode 17. 电话号码的字母组合
    LeetCode 491. 递增的子序列
    LeetCode 459.重复的子字符串
    LeetCode 504. 七进制数
    LeetCode 3.无重复字符的最长子串
    LeetCode 16.06. 最小差
    LeetCode 77. 组合
    LeetCode 611. 有效三角形个数
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3306711.html
Copyright © 2020-2023  润新知