[JZOJ3397]【GDOI2014模拟】雨天的尾巴
来源:互联网 发布:免费抠图软件 编辑:程序博客网 时间:2024/04/30 11:37
Description
深绘里一直很讨厌雨天。
灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。
虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连
根拔起,以及田地里的粮食被弄得一片狼藉。
无奈的深绘里和村民们只好等待救济粮来维生。
不过救济粮的发放方式很特别。
首先村落里的一共有n 座房屋,并形成一个树状结构。然后救济粮分m 次发放,每次选择
两个房屋(x,y),然后对于x 到y 的路径上(含x 和y) 每座房子里发放一袋z 类型的救济粮。
然后深绘里想知道,当所有的救济粮发放完毕后,每座房子里存放的最多的是哪种救济粮
Solution
一道树上路径修改问题
比较恶心的是,最多有
我们先考虑在一个序列上区间修改
把每个区间左边界排序,左边界+1,右边界-1,从左到右扫一遍扔进堆里,然后堆顶就是当前答案
放到树上可以树链剖分,对于每个链操作都是独立的,分开处理就好。
但是,你有没有觉得很麻烦?
仔细研究题目,发现询问并不是动态的。
对于树上每一个点,都维护一个动态开点的以种类为下标的权值线段树,记录最大值和位置。
显然我们不能每个操作都去路径维护。
对于下面这个图
对于多次路径修改,有一种十分经典的做法——线段树合并
关于线段树合并不理解的可以看这里
我们需要对
在
想想为什么
这样到了最后线段树合并的时候,从叶子节点向根逐渐合并,到了
这样可以
有人可能会有疑问,不是每个点都要开一个权值线段树
不虚,我们有动态开节点!
因为每次操作最多新开
合并时并不需要多开节点,详见上面链接
于是我们在
Code
本人特别讨厌线段树,因为每次我都把线段树打的很长很长~~
#include<cstdio>#include<cstdlib>#include<algorithm>#include<iostream>#include<cstring>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)#define fo1(i,a) for(int i=last[k];i;i=next[i])using namespace std;struct note{ int l,r,mx,wz,ls,rs; };struct note1{ int x,y,z;};bool cmp(note1 x,note1 y){ return x.z<y.z;}note tree[5000000];int next[200005],dt[200005],last[100005],first[100005];int n,m,a1[100005][2],ft[100005][17],root[100005],deep[100005],lim,dp,rlim,maxn;int pt[100001];note1 cz[100001];void dfs(int k,int f){ ft[k][0]=f; deep[k]=deep[f]+1; dp=deep[k]; if (deep[k]==43423) { dp++; dp--; } fo1(b,k) if (dt[b]!=f) dfs(dt[b],k); } int lca(int x,int y){ if (deep[x]<deep[y]) swap(x,y); while(deep[x]!=deep[y]) { int i=0; while(deep[ft[x][i]]>=deep[y]) i++; x=ft[x][--i]; } while (x!=y) { int i=0; while (ft[x][i]!=ft[y][i]) i++; if (i==0) return ft[x][0]; x=ft[x][--i]; y=ft[y][i]; } return x;}void buildl(int now,int l,int r){ if (tree[now].ls==0) { tree[now].ls=++lim; tree[lim].l=l; tree[lim].r=r; }}void buildr(int now,int l,int r){ if (tree[now].rs==0) { tree[now].rs=++lim; tree[lim].l=l; tree[lim].r=r; }}void change(int now,int l,int r,int v){ if (tree[now].l==l&&tree[now].r==r) { tree[now].mx+=v; tree[now].wz=l; return; } int mid=(tree[now].l+tree[now].r)/2; if(r<=mid) { buildl(now,tree[now].l,mid); change(tree[now].ls,l,r,v); } else if (l>mid) { buildr(now,mid+1,tree[now].r); change(tree[now].rs,l,r,v); } else { buildl(now,tree[now].l,mid); buildr(now,mid+1,tree[now].r); change(tree[now].ls,l,mid,v); change(tree[now].rs,mid+1,r,v); } int ls=tree[now].ls,rs=tree[now].rs; int x=tree[ls].mx,y=tree[rs].mx,x1=tree[ls].wz,y1=tree[rs].wz; tree[now].mx=(x>=y)?x:y; tree[now].wz=(x>=y)?x1:y1; }void hb(int hf,int hs,int l,int r){ if(l==r) { tree[hf].mx+=tree[hs].mx; tree[hf].wz=l; return; } int lsf=tree[hf].ls,rsf=tree[hf].rs,lss=tree[hs].ls,rss=tree[hs].rs,mid=(l+r)/2; if (lss!=0) { if (lsf==0) tree[hf].ls=lss; else hb(lsf,lss,l,mid); } if (rss!=0) { if (rsf==0) tree[hf].rs=rss; else hb(rsf,rss,mid+1,r); } int x=tree[tree[hf].ls].mx,y=tree[tree[hf].rs].mx,x1=tree[tree[hf].ls].wz,y1=tree[tree[hf].rs].wz; tree[hf].mx=(x>=y)?x:y; tree[hf].wz=(x>=y)?x1:y1; }void merge(int k,int f){ int i; for(int i=last[k];i;i=next[i]) { if (dt[i]!=f) { merge(dt[i],k); hb(root[k],root[dt[i]],1,maxn); } }}int main(){ cin>>n>>m; int i,j; rlim=0; fo(i,1,n-1) { int x,y; rlim++; scanf("%d%d",&x,&y); dt[rlim]=x; if (last[y]==0) last[y]=first[y]=rlim; else { next[first[y]]=rlim; first[y]=rlim; } rlim++; dt[rlim]=y; if (last[x]==0) last[x]=first[x]=rlim; else { next[first[x]]=rlim; first[x]=rlim; } } dfs(1,0); fo(i,1,trunc(log(n)/log(2))) fo(j,1,n) ft[j][i]=ft[ft[j][i-1]][i-1]; fo(i,1,m) { int x,y,z; scanf("%d%d%d",&cz[i].x,&cz[i].y,&cz[i].z); maxn=100000; } sort(cz+1,cz+m+1,cmp); int bi=0; fo(i,1,n) { root[i]=++lim; tree[lim].l=1; tree[lim].r=100000; } fo(i,1,m) { if (cz[i].z!=cz[i-1].z) bi++; pt[bi]=cz[i].z; int x=cz[i].x,y=cz[i].y; int lp=lca(x,y); change(root[x],bi,bi,1); change(root[y],bi,bi,1); change(root[lp],bi,bi,-1); if (lp!=1) change(root[ft[lp][0]],bi,bi,-1); } merge(1,0); fo(i,1,n) printf("%d\n",pt[tree[root[i]].wz]);}
- [JZOJ3397]【GDOI2014模拟】雨天的尾巴
- 【GDOI2014模拟】雨天的尾巴
- 【GDOI2014模拟】雨天的尾巴
- [JZOJ3397]雨天的尾巴
- 【JZOJ3397】雨天的尾巴
- 【GDOI2014模拟】雨天的尾巴 题解+代码
- bzoj3307 雨天的尾巴
- 雨天的尾巴
- [bzoj3307]雨天的尾巴
- 雨天的尾巴
- BZOJ3307: 雨天的尾巴
- bzoj-3307 雨天的尾巴
- bzoj 3307: 雨天的尾巴
- 【JZOJ 3397】 雨天的尾巴
- 【JZOJ 3397】雨天的尾巴
- BZOJ 3307: 雨天的尾巴
- BZOJ 3307 雨天的尾巴 线段树
- 【bzoj3307】雨天的尾巴 线段树+树链剖分
- KL 散度(从动力系统到推荐系统)
- 沼泽鳄鱼 矩阵乘法
- MFC嵌入浏览器框架CEF
- C++运算符重载
- Spring 与依赖注入
- [JZOJ3397]【GDOI2014模拟】雨天的尾巴
- 【SSH网上商城项目实战27】域名空间的申请和项目的部署及发布
- 二叉树--遍历
- Java - 蓝桥杯 - 历届试题 买不到的数目
- Linux虚拟机访问Windows7系统中的文件共享
- java编程方向
- Linux开发环境的搭建与U盘启动的制作
- Problem D
- 第12周阅读程序(3)