zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    linux 下java jar包的方法
    (转)浅谈Java的输入输出流
    把java文件打包成jar文件
    C#ListView控件中列添加控件ComboBox,控件TextBox,添加时间选择列DateTimePicker
    <LabelId>k__BackingField反编译错误修改
    oracleI基础入门(6)sql语句And or Crazy
    oracleI基础入门(6)sql语句distinct Crazy
    oracleI基础入门(6)sql语句Order By Crazy
    oracleI基础入门(6)sql语句Like Crazy
    oracleI基础入门(6)sql语句count Crazy
  • 原文地址:https://www.cnblogs.com/kuangbin/p/3306711.html
Copyright © 2011-2022 走看看