【Bzoj4353】play with tree
来源:互联网 发布:单台mysql最大tps 编辑:程序博客网 时间:2024/06/07 03:50
题意
给你一棵包含N个节点的树,设每条边一开始的边权为0,现在有两种操作:
1)给出参数U,V,C,表示把U与V之间的路径上的边权变成C(保证C≥0)
2)给出参数U,V,C,表示把U与V之间的路径上的边权加上C。但是如果U至V之间路径某条边的边权加上C小于0,那么C=这条边的边权的相反数。
你需要统计出每次一操作过后树中边权为0的边有多少条。
解析
边权树链剖分。对于操作1直接修改,对于操作2,先检测树链上最小值,看要不要改C,然后再加。每次查的话如果Tn[i]=0就累加答案。注意事项的话就是合并的时候看两边最小值是否一样。还有修改和覆盖的关系要搞清。
#include <cstdio>#include <algorithm>#define Rep( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i<=(i##_END);i++)#define For( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i++)#define Lop( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i>=(i##_END);i--)#define Dnt( i , _begin , _end ) for(int i=(_begin),i##_END=(_end);i!=(i##_END);i--)using std :: max;using std :: min;const int maxx = 200000 + 25;const int Inf = (unsigned)(-1) >> 1;typedef int Array[maxx];int n,m,x,y,z,num,tot,ans,f;int head[maxx],to[maxx<<1],nxt[maxx<<1],w[maxx<<1];int Tn[maxx<<2],cnt[maxx<<2],Add[maxx<<2],st[maxx<<2];Array top,size,ftr,son,dpt,rnk;namespace Cute{ void Ins(int x,int y){ to[++num] = y;nxt[num] = head[x];head[x] = num; } void Dfs(int x){ size[x] = 1; for(int i=head[x];i;i=nxt[i]){ if(to[i] == ftr[x]) continue; dpt[to[i]] = dpt[x] + 1; ftr[to[i]] = x; Dfs(to[i]);size[x] += size[to[i]]; if(size[to[i]] > size[son[x]]) son[x] = to[i]; } } void __Dfs(int x,int brn){ top[x] = brn;rnk[x] = ++tot; if(son[x]) __Dfs(son[x],brn); for(int i=head[x];i;i=nxt[i]) if(to[i] != ftr[x] && to[i] != son[x]) __Dfs(to[i],to[i]); }}namespace Segment_Tree{ void upt(int i){ if(Tn[i<<1] == Tn[i<<1|1]) {Tn[i] = Tn[i<<1];cnt[i] = cnt[i<<1] + cnt[i<<1|1];return;} Tn[i] = min(Tn[i<<1],Tn[i<<1|1]); cnt[i] = Tn[i<<1] < Tn[i<<1|1]? cnt[i<<1] : cnt[i<<1|1]; } void Build(int i,int l,int r){ st[i] = -1; if(l == r) {Tn[i] = 0;cnt[i] = 1;return;} int mid = (l+r) >> 1; Build(i<<1,l,mid);Build(i<<1|1,mid+1,r); upt(i); } void pushdown(int i,int l,int r){ int mid = (l+r) >> 1; if(st[i] != -1){ st[i<<1] = st[i];Add[i<<1] = 0;Tn[i<<1] = st[i];cnt[i<<1] = (mid-l+1); st[i<<1|1] = st[i];Add[i<<1|1] = 0;Tn[i<<1|1] = st[i];cnt[i<<1|1] = (r-mid); st[i] = -1; } if(Add[i]){ Add[i<<1] += Add[i];Tn[i<<1] += Add[i]; Add[i<<1|1] += Add[i];Tn[i<<1|1] += Add[i]; Add[i] = 0; } } void modify(int i,int x,int y,int l,int r,int f,int k){ if(x <= l && r <= y){ if(f == 1) {Tn[i] += k;Add[i] += k;return;} if(f == 2) {st[i] = k;Tn[i] = k;Add[i] = 0;cnt[i] = (r-l+1);return;} } int mid = (l+r) >> 1; pushdown(i,l,r); if(x <= mid) modify(i<<1,x,y,l,mid,f,k); if(y > mid) modify(i<<1|1,x,y,mid+1,r,f,k); upt(i); } int Query(int i,int x,int y,int l,int r){ int ans = Inf; if(x <= l && r <= y) return Tn[i]; int mid = (l+r) >> 1; pushdown(i,l,r); if(x <= mid) ans = min(ans,Query(i<<1,x,y,l,mid)); if(y > mid) ans = min(ans,Query(i<<1|1,x,y,mid+1,r)); return ans; } int Getcnt(int i,int x,int y,int l,int r){ if(x <= l && r <= y) return Tn[i]==0? cnt[i] : 0; int ans = 0; int mid = (l+r) >> 1; pushdown(i,l,r); if(x <= mid) ans += Getcnt(i<<1,x,y,l,mid); if(y > mid) ans += Getcnt(i<<1|1,x,y,mid+1,r); return ans; }}namespace Sb_Linux{ using namespace Segment_Tree; int Get(int x,int y){ int ans = Inf; while(top[x] != top[y]){ if(dpt[top[x]] > dpt[top[y]]) std :: swap(x,y); ans = min(ans,Query(1,rnk[top[y]],rnk[y],1,n)); y = ftr[top[y]]; } if(rnk[x] > rnk[y]) std :: swap(x,y); if(x != y) ans = min(ans,Query(1,rnk[x]+1,rnk[y],1,n)); return ans; } void C(int x,int y,int f,int k){ if(f == 1){ int tmp = Get(x,y); if(tmp + k < 0) k = -tmp; } while(top[x] != top[y]){ if(dpt[top[x]] > dpt[top[y]]) std :: swap(x,y); modify(1,rnk[top[y]],rnk[y],1,n,f,k); y = ftr[top[y]]; } if(rnk[x] > rnk[y]) std :: swap(x,y); if(x != y) modify(1,rnk[x]+1,rnk[y],1,n,f,k); }}using namespace Cute;using namespace Segment_Tree;using namespace Sb_Linux;int main(){ scanf("%d%d",&n,&m); For( i , 1 , n ) scanf("%d%d",&x,&y),Ins(x,y),Ins(y,x); Dfs(1);__Dfs(1,1); Build(1,1,n); while( m-- ){ scanf("%d%d%d%d",&f,&x,&y,&z); if(f == 1) C(x,y,2,z); if(f == 2) C(x,y,1,z); printf("%d\n",Getcnt(1,2,n,1,n)); } return 0;}
阅读全文
0 0
- 【Bzoj4353】play with tree
- 【BZOJ4353】Play with tree,树链剖分线段树
- [BZOJ4353]Play with tree(树链剖分+线段树)
- HDU 3487 Play with Chain (Splay tree)
- hdu-3487-Play with Chain (Splay tree)
- 【splay tree】 HDOJ 3487 Play with Chain
- hdu 3487 Play with Chain splay tree
- hdu 3487 Play with Chain splay tree
- bzoj 4353: Play with tree (树链剖分)
- hdu 3487 Play with Chain(splay tree)
- HDU 3487——Play with Chain(splay tree)
- hdu 3487 Play with Chain (Splay tree基础)
- HDOJ 题目3487 Play with Chain(Splay Tree)
- HDU 3487 Play with Chain (Splay tree)区间切割和反转操作。
- Sound play with stream
- Play with Bindings
- Play with libvirt
- play with the winner
- 动脉硬化知识系列:开篇和生化检测科普1
- ORA-00600: 内部错误代码, 参数: [rwoirw: check ret val], [], [], [], [], [], [], [], [], [], [], []
- NET下的流程图开发包介绍
- 什么是死锁?
- 关于为什么malloc开辟的空间,free后再linux下还可以打印出原来的内容
- 【Bzoj4353】play with tree
- PAT乙级 1036. 跟奥巴马一起编程(15)
- 机器学习--生成学习算法
- poj2386——油田问题(简单搜索)
- 浮动
- c#设计模式之原型模式
- php 获取两个时间戳相差的月份
- 简要分析并搞懂9个tcp基础包------三次握手 + 发送数据并收到确认 + 四次挥手
- R语言 实例操作