【JZOJ3397】雨天的尾巴
来源:互联网 发布:mysql 死锁 编辑:程序博客网 时间:2024/04/20 15:17
Description
深绘里一直很讨厌雨天。
灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。
虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连
根拔起,以及田地里的粮食被弄得一片狼藉。
无奈的深绘里和村民们只好等待救济粮来维生。
不过救济粮的发放方式很特别。
首先村落里的一共有n 座房屋,并形成一个树状结构。然后救济粮分m 次发放,每次选择
两个房屋(x,y),然后对于x 到y 的路径上(含x 和y) 每座房子里发放一袋z 类型的救济粮。
然后深绘里想知道,当所有的救济粮发放完毕后,每座房子里存放的最多的是哪种救济粮。
Solution
首先所有的操作是已经给定的,询问都是固定的。
我们考虑在序列上做覆盖,在左右端点加1减1,维护最大值即可。
如果在树上,那我们先把树剖成一条条链,再在上面做覆盖即可。时间复杂度O(
可不可以不这么麻烦呢?我们直接考虑树上覆盖。
显然,在左端点
于是我们动态开一棵权值线段树,维护每个点最大值的编号。
操作完成后,对于原图每个节点,我们把它与儿子节点合并线段树,对于这题来说,合并就是把个数加起来即可。
这样合并一次是
Code
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define N 100001#define M 200001#define mo 200007using namespace std;int to[M],next[M],last[M],num=0;int d[N],f[N][21];struct node{ int l,r; int mx;}tr[N*50];int a[N];int h[mo];int b[N];int tot=0;int hash(int x){ int p=x%mo; while(h[p] && h[p]!=x) p=(p+1)%mo; h[p]=x; return p;}void link(int x,int y){ num++; to[num]=y; next[num]=last[x]; last[x]=num;}int cnt=0;void find(int x){ for(int i=last[x];i;i=next[i]) { int v=to[i]; if(v!=f[x][0]) { f[v][0]=x; d[v]=d[x]+1; find(v); } }}int lca(int x,int y){ int tmp=0; if(d[x]>d[y]) swap(x,y); fd(i,14,0) while(d[f[y][i]]>=d[x]) y=f[y][i]; fd(i,14,0) while(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; if(x!=y) x=f[x][0],y=f[y][0]; return x;}void change(int v,int l,int r,int x,int p){ if(l==r && l==x) { tr[v].mx+=p; return; } int mid=(l+r)/2; if(x<=mid) { if(!tr[v].l) tr[v].l=++tot; change(tr[v].l,l,mid,x,p); } else { if(!tr[v].r) tr[v].r=++tot; change(tr[v].r,mid+1,r,x,p); } int i=tr[v].l,j=tr[v].r; tr[v].mx=max((!i?0:tr[i].mx),(!j?0:tr[j].mx));}void merge(int v,int vv,int l,int r){ if(l==r) { tr[v].mx+=tr[vv].mx; return; } int mid=(l+r)/2; if(tr[vv].l) { if(!tr[v].l) tr[v].l=tr[vv].l; else merge(tr[v].l,tr[vv].l,l,mid); } if(tr[vv].r) { if(!tr[v].r) tr[v].r=tr[vv].r; else merge(tr[v].r,tr[vv].r,mid+1,r); } int i=tr[v].l,j=tr[v].r; tr[v].mx=max((!i?0:tr[i].mx),(!j?0:tr[j].mx));}int findans(int v,int l,int r){ if(l==r) return l; int mid=(l+r)/2; int i=tr[v].l,j=tr[v].r; if(tr[i].mx>=tr[j].mx) findans(i,l,mid); else findans(j,mid+1,r);}int lyd=0;void dfs(int x){ for(int i=last[x];i;i=next[i]) { int v=to[i]; if(v!=f[x][0]) { dfs(v); merge(a[x],a[v],1,mo-1); } } b[x]=findans(a[x],1,mo-1);}int main(){ int n,m; cin>>n>>m; fo(i,1,n-1) { int x,y; scanf("%d %d",&x,&y); link(x,y); link(y,x); } find(1); fo(j,1,20) fo(i,1,n) f[i][j]=f[f[i][j-1]][j-1]; fo(i,1,n) a[i]=i; tot=n; d[0]=-1; fo(i,1,m) { int x,y,z; scanf("%d %d %d",&x,&y,&z); int p=hash(z); change(a[x],1,mo-1,z,1); change(a[y],1,mo-1,z,1); int t=lca(x,y); change(a[t],1,mo-1,z,-1); change(a[f[t][0]],1,mo-1,z,-1); } dfs(1); fo(i,1,n) printf("%d\n",h[b[i]]);}
1 0
- [JZOJ3397]雨天的尾巴
- 【JZOJ3397】雨天的尾巴
- [JZOJ3397]【GDOI2014模拟】雨天的尾巴
- bzoj3307 雨天的尾巴
- 雨天的尾巴
- [bzoj3307]雨天的尾巴
- 雨天的尾巴
- BZOJ3307: 雨天的尾巴
- bzoj-3307 雨天的尾巴
- bzoj 3307: 雨天的尾巴
- 【JZOJ 3397】 雨天的尾巴
- 【JZOJ 3397】雨天的尾巴
- 【GDOI2014模拟】雨天的尾巴
- 【GDOI2014模拟】雨天的尾巴
- BZOJ 3307: 雨天的尾巴
- BZOJ 3307 雨天的尾巴 线段树
- 【bzoj3307】雨天的尾巴 线段树+树链剖分
- 【GDOI2014模拟】雨天的尾巴 题解+代码
- nrf51822学习之BLE400初次接触
- 【Leetcode】TwoSum的解析
- 小型电子商务网站数据管理系统
- PHP集成包
- android MVP——mvp架构的应用和优化
- 【JZOJ3397】雨天的尾巴
- 回调函数初识
- Unity 4.x 各版本IOS IL2CPP对比
- 剑指offer之编程(十三)
- Android学习笔记(2)
- kaggle 入门 Bike sharing Demand prediction
- Python中sorted()方法的用法
- ffmpeg常见的命令行参数
- 1007