SPOJ - COT Count on a tree
地址:http://www.spoj.com/problems/COT/en/
题目:
COT - Count on a tree
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
7
思路: 这是一道求树上两点uv路径上的第k大权值的题。
求第k大很容易想到主席树,但是以前的主席树的都是线性的,这题却是树型的。
其实只需要把建树的方式改成根据父亲节点建树即可,查询时:sum[u]+sum[v]-sum[lca(u,v)]-sum[fa[lca(u,v)]]。
这还是一道模板题。
1 #include <bits/stdc++.h>
2
3 using namespace std;
4
5 #define MP make_pair
6 #define PB push_back
7 typedef long long LL;
8 typedef pair<int,int> PII;
9 const double eps=1e-8;
10 const double pi=acos(-1.0);
11 const int K=2e6+7;
12 const int mod=1e9+7;
13
14 int tot,ls[K],rs[K],rt[K],sum[K];
15 int v[K],b[K],up[K][25],deep[K],fa[K];
16 vector<int>mp[K];
17 //sum[o]记录的是该节点区间内出现的数的个数
18 //区间指的是将数离散化后的区间
19 void build(int &o,int l,int r)
20 {
21 o=++tot,sum[o]=0;
22 int mid=l+r>>1;
23 if(l!=r)
24 build(ls[o],l,mid),build(rs[o],mid+1,r);
25 }
26 void update(int &o,int l,int r,int last,int x)
27 {
28 o=++tot,sum[o]=sum[last]+1;
29 ls[o]=ls[last],rs[o]=rs[last];
30 if(l==r) return ;
31 int mid=l+r>>1;
32 if(x<=mid) update(ls[o],l,mid,ls[last],x);
33 else update(rs[o],mid+1,r,rs[last],x);
34 }
35 int query(int ra,int rb,int rc,int rd,int l,int r,int k)
36 {
37 if(l==r) return b[l];
38 int cnt=sum[ls[ra]]+sum[ls[rb]]-sum[ls[rc]]-sum[ls[rd]],mid=l+r>>1;
39 if(k<=cnt) return query(ls[ra],ls[rb],ls[rc],ls[rd],l,mid,k);
40 return query(rs[ra],rs[rb],rs[rc],rs[rd],mid+1,r,k-cnt);
41 }
42 void dfs(int x,int f,int sz)
43 {
44 update(rt[x],1,sz,rt[f],v[x]);
45 up[x][0]=f,deep[x]=deep[f]+1,fa[x]=f;
46 for(int i=1;i<=20;i++) up[x][i]=up[up[x][i-1]][i-1];
47 for(int i=0;i<mp[x].size();i++)
48 if(mp[x][i]!=f)
49 dfs(mp[x][i],x,sz);
50 }
51 int lca(int x,int y)
52 {
53 if(deep[x]<deep[y]) swap(x,y);
54 for(int i=20;i>=0;i--) if( deep[up[x][i]]>=deep[y]) x=up[x][i];
55 if(x==y) return x;
56 for(int i=20;i>=0;i--) if(up[x][i]!=up[y][i]) x=up[x][i],y=up[y][i];
57 return up[x][0];
58 }
59 int main(void)
60 {
61 tot=0;
62 int n,m,sz;
63 scanf("%d%d",&n,&m);
64 for(int i=1;i<=n;i++)
65 scanf("%d",v+i),b[i]=v[i];
66 for(int i=1,x,y;i<n;i++)
67 scanf("%d%d",&x,&y),mp[x].PB(y),mp[y].PB(x);
68 sort(b+1,b+1+n);
69 sz=unique(b+1,b+1+n)-b-1;
70 for(int i=1;i<=n;i++)
71 v[i]=lower_bound(b+1,b+1+sz,v[i])-b;
72 build(rt[0],1,sz);
73 dfs(1,0,sz);
74 int x,y,k;
75 while(m--)
76 scanf("%d%d%d",&x,&y,&k),printf("%d\n",query(rt[x],rt[y],rt[lca(x,y)],rt[fa[lca(x,y)]],1,sz,k));
77 return 0;
78 }
作者:weeping
出处:www.cnblogs.com/weeping/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。