Gym 101161E 主席树+LCA
来源:互联网 发布:中国经济实力 知乎 编辑:程序博客网 时间:2024/05/17 12:02
题意
给一棵树,问树上路径权值中位数。
题解
树上路径权值中位数就是求第k/2大数,很明显主席树+LCA。这道题还是比较容易的,有一点非常重要的是权值W的范围是1-100000,这个范围很大程度上影响了题目的实现难度。由于权值最大只有10万,因此我们可以搞一个10万的主席树,这样的话每一次查询第K大,我们可以利用主席树去针对某一段版本的线段树去查询,从右到左的第K的数字就是第K大。
搞明白了这个,还有一个需要搞明白的就是树上的查询需要用v[a]+v[b]-2*v[lca(a,b)]。这样一减求的就是路径上的值。
代码
#include<bits/stdc++.h>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(t) while(t)#define MEM(a,b) memset(a,b,sizeof(a))#define LL long long#define INF 0x3f3f3f3f#define EPS 1e-8#define MAXN 50010#define MOD 100000007#define COUT(x) cout<<x<<endlusing namespace std;struct Edge{ int to,w; Edge(int to=0,int w=0):to(to),w(w){}};vector<Edge> vc[MAXN];const int NN=25001000;int dep[MAXN],sum[NN],ln[NN],rn[NN],root[MAXN];int anc[MAXN][25];int tot;int update(int o,int L,int l,int r){// COUT(o<<" "<<l<<" "<<r); int k=++tot; sum[k]=sum[o],ln[k]=ln[o],rn[k]=rn[o]; sum[k]++; if(l==r) return k; int m=(l+r)/2; if(L<=m) ln[k]=update(ln[k],L,l,m); else rn[k]=update(rn[k],L,m+1,r); return k;}int query(int a,int b,int f,int L,int l,int r){ if(l==r) return l; int m=(l+r)/2; int tmp=(sum[ln[b]]+sum[ln[a]]-2*sum[ln[f]]); if(L<=tmp) return query(ln[a],ln[b],ln[f],L,l,m); else return query(rn[a],rn[b],rn[f],L-tmp,m+1,r);}void dfs(int u,int f,int deep){// COUT("dfs"<<u); dep[u]=deep; anc[u][0]=f;// COUT(u<<" "<<f); UP(i,1,20){ anc[u][i]=anc[anc[u][i-1]][i-1]; } for(Edge v:vc[u]){ if(f==v.to) continue; root[v.to]=update(root[u],v.w,1,100000); dfs(v.to,u,deep+1); }}int lca(int a,int b){ if(dep[a]<dep[b]) swap(a,b);// COUT(a<<" "<<b); DOWN(i,20,0){// COUT(dep[anc[a][i]]<<" "<<dep[b]); if(dep[b]<=dep[anc[a][i]]) a=anc[a][i]; }// COUT(a<<" "<<b); if(a==b) return a; DOWN(i,20,0){ if(anc[a][i]!=anc[b][i]){ a=anc[a][i]; b=anc[b][i]; } } return anc[a][0];}int main(){ int t; scanf("%d",&t); W(t--){ MEM(vc,0); MEM(anc,0); MEM(dep,0); MEM(sum,0); MEM(ln,0); MEM(rn,0); MEM(root,0); tot=0; int n,q; scanf("%d",&n); UP(i,0,n-1){ int u,v,w; scanf("%d%d%d",&u,&v,&w); vc[u].push_back(Edge(v,w)); vc[v].push_back(Edge(u,w)); } scanf("%d",&q); dfs(1,0,1); W(q--){ int a,b; scanf("%d%d",&a,&b); int fa=lca(a,b);// COUT(dep[a]<<" "<<dep[b]);// COUT(fa); int cot=dep[a]+dep[b]-2*dep[fa];// COUT(cot); if(cot%2==1){ printf("%.1f\n",(double)query(root[a],root[b],root[fa],(cot+1)/2,1,100000)); }else{// COUT((double)query(root[a],root[b],root[fa],cot/2,1,100000)<<" "<<(double)query(root[a],root[b],root[fa],cot/2+1,1,100000)); printf("%.1f\n",((double)query(root[a],root[b],root[fa],cot/2,1,100000)+(double)query(root[a],root[b],root[fa],cot/2+1,1,100000))/2); } } }}
阅读全文
0 0
- Codeforces Gym-101161E【LCA+主席树】
- Gym 101161E 主席树+LCA
- 主席树+LCA+spoj10628
- Duff in the Army codeforces 588E 树上主席树+lca
- SPOJ COT (主席树 LCA)
- BZOJ 2588 LCA + 主席树
- Gym 101161 E
- bzoj 4539: [Hnoi2016]树 主席树&lca
- BZOJ 3123 LCA + 主席树 + 启发式合并
- Gym 100499E (树DP)
- Gym-101612E E
- Codeforces 813E Army Creation [主席树]
- GYM 100883 E.xortion(字典树)
- bzoj 4539: [Hnoi2016]树(缩点+主席树+lca)
- [BZOJ4539][Hnoi2016]树(dfs序+主席树+lca)
- bzoj 4539 [Hnoi2016]树 主席树 倍增lca
- 【BZOJ 4539】[Hnoi2016]树 倍增lca+主席树
- [BZOJ4539][Hnoi2016]树(倍增+LCA+主席树)
- Java集合——HashSet
- 电子邮件未能发送。 可能原因:您的主机禁用了mail()函数。
- Spark2.2.0分布式集群搭建教程
- 数据结构|顺序队列的实现(实验3.3)
- java Applet(web网页动态交互性)
- Gym 101161E 主席树+LCA
- 字节协议理解和处理
- QT Create 学习之 QTreeWidget
- 九度OJ-1001
- OpenStack安装全过程
- php类自动载入
- jQuery的事件委托机制和事件绑定的区别
- 欢迎使用CSDN-markdown编辑器
- Java中的反射机制