主席树+LCA+spoj10628
来源:互联网 发布:怎么添加网络打印机xp 编辑:程序博客网 时间:2024/06/05 18:08
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 58 5105 2 9 3 8 5 7 71 2 1 31 43 53 63 74 82 5 12 5 22 5 32 5 47 8 2
Output:2891057
题意:给出一棵树,询问两点之间第k小的权值是多少
思路:主席树记录从根节点到当前节点出现在1..m(权值按从小到大排序后)中的数(跟poj2104求区间第k小的数一样,这里只不过是书上从根到当前节点),这样当查询时候
在线求出u,v的lca,然后就跟查询区间第k小的值一样了
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;const int maxn=200010;const int maxm=maxn*50;int N,M,m,num;int w[maxn];int order[maxn],cnt[maxm],lson[maxm],rson[maxm],T[maxm];int E[maxn*2],dep[maxn*2],pos[maxn],vis[maxn];int d[maxn*2][20];int head[maxn];struct node{ int v,next;}edge[maxn*2];void add_edge(int u,int v){ edge[num].v=v; edge[num].next=head[u]; head[u]=num++;}void init(){ num=0; for(int i=0;i<=N;i++) { vis[i]=0; pos[i]=head[i]=-1; } for(int i=1;i<=N;i++)order[i]=w[i]; sort(order+1,order+1+N); m=unique(order+1,order+1+N)-order-1;}//LCA部分void LCA_dfs(int u,int depth){ E[++num]=u,dep[num]=depth; if(pos[u]==-1)pos[u]=num; vis[u]=1; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(vis[v])continue; LCA_dfs(v,depth+1); E[++num]=u; dep[num]=depth; }}void initRMQ(int n){ for(int i=0;i<=n;i++)d[i][0]=i; for(int j=1;(1<<j)<=n;j++) { for(int i=1;i+(1<<j)<=n;i++) { int x=d[i][j-1],y=d[i+(1<<(j-1))][j-1]; if(dep[x]<=dep[y])d[i][j]=x; else d[i][j]=y; } }}int LCA_query(int u,int v){ int x=pos[u],y=pos[v]; if(x>y)swap(x,y); int k=0; while((1<<(k+1))<=y-x+1)k++; int l=d[x][k],r=d[y-(1<<k)+1][k]; if(dep[l]<=dep[r])return E[l]; else return E[r];}//主席树部分int build(int l,int r){ int root=num++; cnt[root]=0; if(l!=r) { int mid=(l+r)>>1; lson[root]=build(l,mid); rson[root]=build(mid+1,r); } return root;}int update(int root,int pos,int val){ int newroot=num++,tmp=newroot; int l=1,r=m; cnt[newroot]=cnt[root]+val; while(l<r) { int mid=(l+r)>>1; if(pos<=mid) { r=mid; lson[newroot]=num++,rson[newroot]=rson[root]; newroot=lson[newroot],root=lson[root]; } else { l=mid+1; rson[newroot]=num++,lson[newroot]=lson[root]; newroot=rson[newroot],root=rson[root]; } cnt[newroot]=cnt[root]+val; } return tmp;}int find(int x){ return lower_bound(order+1,order+1+m,x)-order;}void dfs_build(int u,int fa){ int pos=find(w[u]); T[u]=update(T[fa],pos,1); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==fa)continue; dfs_build(v,u); }}int query(int left,int right,int lca,int k){ int l=1,r=m; int pos=find(w[lca]); lca=T[lca]; while(l<r) { int mid=(l+r)>>1; //注意减掉两倍的lca后,相当于lca这个点没有了,要判断是不是应该加上 int tmp=cnt[lson[left]]+cnt[lson[right]]-2*cnt[lson[lca]]+(pos>=l&&pos<=mid); if(tmp>=k) { r=mid; left=lson[left]; right=lson[right]; lca=lson[lca]; } else { l=mid+1; k-=tmp; left=rson[left]; right=rson[right]; lca=rson[lca]; } } return l;}int main(){ while(scanf("%d%d",&N,&M)!=EOF) { for(int i=1;i<=N;i++) scanf("%d",&w[i]); init(); for(int i=1;i<N;i++) { int u,v; scanf("%d%d",&u,&v); add_edge(u,v); add_edge(v,u); } num=0; LCA_dfs(1,1); initRMQ(num); num=0; T[0]=build(1,m); dfs_build(1,0); while(M--) { int u,v,k; scanf("%d%d%d",&u,&v,&k); int lca=LCA_query(u,v); printf("%d\n",order[query(T[u],T[v],lca,k)]); } } return 0;}
- 主席树+LCA+spoj10628
- BZOJ-2588-Count-on-a-tree-SPOJ10628-LCA+主席树
- 函数式线段树(主席树)学习实践spoj10628
- SPOJ10628--COT(树上第K大)主席树
- [BZOJ2588][Spoj10628]Count on a tree(树上主席树)
- SPOJ COT (主席树 LCA)
- BZOJ 2588 LCA + 主席树
- bzoj 4539: [Hnoi2016]树 主席树&lca
- Codeforces Gym-101161E【LCA+主席树】
- BZOJ 3123 LCA + 主席树 + 启发式合并
- Gym 101161E 主席树+LCA
- bzoj 4539: [Hnoi2016]树(缩点+主席树+lca)
- [BZOJ4539][Hnoi2016]树(dfs序+主席树+lca)
- bzoj 4539 [Hnoi2016]树 主席树 倍增lca
- 【BZOJ 4539】[Hnoi2016]树 倍增lca+主席树
- [BZOJ4539][Hnoi2016]树(倍增+LCA+主席树)
- SPOJ COT 树上第K大(LCA+主席树)
- spoj 10628 Count on a tree (主席树+lca)
- 【HEVC学习与研究】36、对帧内预测参考数据进行滤波处理
- 【FZU 1978】Repair the brackets (Splay)
- C#里using的妙用(释放资源)
- Bridge模式(桥接模式 )
- 提高程序员工作效率的5个诀窍
- 主席树+LCA+spoj10628
- Linq to SQL查询数据库
- 迎接iOS8 - CoreLocation的变化
- 我的3d打印机制作心得
- android异步任务详解 AsynTask
- 【Unity Shaders】使用Unity Render Textures实现画面特效——画面特效中的叠加(Overlay)混合模式
- NYOJ-整数性质【扩展欧几里得】
- 线程和进程之我见
- 多人协作