【GDOI2014模拟】雨天的尾巴
来源:互联网 发布:金海岸大酒店网络地图 编辑:程序博客网 时间:2024/05/01 12:50
题目
深绘里一直很讨厌雨天。
灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。
虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连
根拔起,以及田地里的粮食被弄得一片狼藉。
无奈的深绘里和村民们只好等待救济粮来维生。
不过救济粮的发放方式很特别。
首先村落里的一共有n 座房屋,并形成一个树状结构。然后救济粮分m 次发放,每次选择
两个房屋(x,y),然后对于x 到y 的路径上(含x 和y) 每座房子里发放一袋z 类型的救济粮。
然后深绘里想知道,当所有的救济粮发放完毕后,每座房子里存放的最多的是哪种救济粮。
分析
相信大多数人都跟我一样,看到这道题,果断认为是树链剖分。
其实不然(我1.5h把熟练剖分打出来,以为能过50%。结果打错了,20%。然后。。。打暴力的人都是50%,#%……&*)。
我们注意到z<=10^9,那么**的数据范围。
但是m<=100000,所以就先做个离散化。
。。。
接着用到个很神奇的东西,叫线段树合并。
对于树上的每一个节点开一棵线段树,记录该节点的每个z的数量以及某一段z的最大值。注意要动态开节点,否则会爆空间。
发现,如果要修改从x到y的路径,其实就是将x的z值加一,y的z值加一,lca(x,y)的z值减一以及fa[lca(x,y)]的z值减一(why?因为当线段树合并后从x到lca(x,y)的路径上和从y到lca(x,y)的路径上的每个节点的z值都加一,但lca(x,y)这个节点重复加了,那么就减掉。不过剩余的z值还会继续上传,所以在fa[lca(x,y)]就把上传的z值减去)
合并操作
int mesh(int x,int y,int l,int r){ if(l==r) { tree[x].v+=tree[y].v; return 0; } int mid=(l+r)/2; if(tree[y].l) { if(!tree[x].l) tree[x].l=tree[y].l; else mesh(tree[x].l,tree[y].l,l,mid); } if(tree[y].r) { if(!tree[x].r) tree[x].r=tree[y].r; else mesh(tree[x].r,tree[y].r,mid+1,r); } tree[x].v=max(tree[tree[x].l].v,tree[tree[x].r].v);}
当然,当所有的修改操作做完后才线段树合并,否则会超时。
#include <cmath>#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <queue>const int maxlongint=2147483647;using namespace std;struct trees{ int l,r,v;}tree[8000000];struct read{ int x,y,z;}re[110000];int next[201000],last[201000],to[201000],po,tot,n,m,g[200000][20],t[200000],deep[200000],f[200000],sum,ans[2000000];bool cmp(read x,read y){ return x.z<y.z;}int bj(int x,int y){ next[++tot]=last[x]; last[x]=tot; to[tot]=y;}int dg(int x){ for(int i=last[x];i;i=next[i]) { int j=to[i]; if(j!=g[x][0]) { deep[j]=deep[x]+1; g[j][0]=x; dg(j); } }}int prelca(){ for(int j=1;j<=log2(n);j++) { for(int i=1;i<=n;i++) { g[i][j]=g[g[i][j-1]][j-1]; } }}int lca(int x,int y){ if(deep[x]>deep[y]) { x=x^y; y=x^y; x=x^y; } for(int i=log2(n);i>=0;i--) { if(deep[g[y][i]]>deep[x]) y=g[y][i]; } if(deep[y]!=deep[x]) y=g[y][0]; for(int i=log2(n);i>=0;i--) { if(g[y][i]!=g[x][i]) { y=g[y][i]; x=g[x][i]; } } if(x!=y) y=g[y][0]; return y;}int put(int v,int l,int r,int x,int y){ if(l==r) { tree[v].v+=y; return 0; } int mid=(l+r)/2; if(x<=mid) { if(!tree[v].l) tree[v].l=++sum; put(tree[v].l,l,mid,x,y); } else { if(!tree[v].r) tree[v].r=++sum; put(tree[v].r,mid+1,r,x,y); } tree[v].v=max(tree[tree[v].l].v,tree[tree[v].r].v);}int work(int x,int y,int z){ int lc=lca(x,y); if(!f[x]) { f[x]=++sum; } put(f[x],1,tot,z,1); if(!f[y]) { f[y]=++sum; } put(f[y],1,tot,z,1); if(!f[lc]) { f[lc]=++sum; } put(f[lc],1,tot,z,-1); if(g[lc][0]) { if(!f[g[lc][0]]) f[g[lc][0]]=++sum; put(f[g[lc][0]],1,tot,z,-1); }}int mesh(int x,int y,int l,int r){ if(l==r) { tree[x].v+=tree[y].v; return 0; } int mid=(l+r)/2; if(tree[y].l) { if(!tree[x].l) tree[x].l=tree[y].l; else mesh(tree[x].l,tree[y].l,l,mid); } if(tree[y].r) { if(!tree[x].r) tree[x].r=tree[y].r; else mesh(tree[x].r,tree[y].r,mid+1,r); } tree[x].v=max(tree[tree[x].l].v,tree[tree[x].r].v);}int find(int v,int l,int r){ if(l==r) { return l; } if(tree[tree[v].l].v==0 && tree[tree[v].r].v==0) return 0; int mid=(l+r)/2; if(tree[tree[v].l].v>=tree[tree[v].r].v) { return find(tree[v].l,l,mid); } else { return find(tree[v].r,mid+1,r); }}int merge(int x){ for(int i=last[x];i;i=next[i]) { int j=to[i]; if(j!=g[x][0]) { merge(j); if(!f[x]) { f[x]=++sum; } if(!f[j]) { f[j]=++sum; } mesh(f[x],f[j],1,tot); } } ans[x]=find(f[x],1,tot);}int main(){ scanf("%d",&n); scanf("%d",&m); for(int i=1;i<=n-1;i++) { int x,y; scanf("%d%d",&x,&y); bj(x,y); bj(y,x); } deep[1]=1; dg(1); prelca(); for(int i=1;i<=m;i++) { scanf("%d%d%d",&re[i].x,&re[i].y,&re[i].z); } sort(re+1,re+m+1,cmp); tot=0; sum=0; for(int i=1;i<=m;i++) { if(re[i].z==t[tot]) { re[i].z=tot; } else { t[++tot]=re[i].z; re[i].z=tot; } } for(int i=1;i<=m;i++) { work(re[i].x,re[i].y,re[i].z); } merge(1); for(int i=1;i<=n;i++) { if(!f[i]) { f[i]=++sum; } printf("%d\n",t[ans[i]]); }}
- 【GDOI2014模拟】雨天的尾巴
- 【GDOI2014模拟】雨天的尾巴
- [JZOJ3397]【GDOI2014模拟】雨天的尾巴
- 【GDOI2014模拟】雨天的尾巴 题解+代码
- bzoj3307 雨天的尾巴
- 雨天的尾巴
- [bzoj3307]雨天的尾巴
- [JZOJ3397]雨天的尾巴
- 雨天的尾巴
- 【JZOJ3397】雨天的尾巴
- BZOJ3307: 雨天的尾巴
- bzoj-3307 雨天的尾巴
- bzoj 3307: 雨天的尾巴
- 【JZOJ 3397】 雨天的尾巴
- 【JZOJ 3397】雨天的尾巴
- BZOJ 3307: 雨天的尾巴
- BZOJ 3307 雨天的尾巴 线段树
- 【bzoj3307】雨天的尾巴 线段树+树链剖分
- 系统流量变化的原因与微型气泵的关系
- sqlite3基本语法
- android-----自定义View实现系列(一)
- 动态改变tableCell的高度
- iOS UIBezierPath图形绘制
- 【GDOI2014模拟】雨天的尾巴
- Docker 入门教程(七)
- 怎么给ChemDraw反应式添加分数系数
- Iphone各个型号机型的尺寸
- JS控制弹窗
- [置顶] 能够提高开发效率的Eclipse实用操作
- 练习 2.14 2.7 2.8 ~ 2.16 未完...
- 随机存储流笔记
- ibatis中常用的代码片段总结