[BZOJ4127][树链剖分][线段树][乱搞]Abs
来源:互联网 发布:it.hasprevious 编辑:程序博客网 时间:2024/05/03 09:19
题意
给定一棵树,设计数据结构支持以下操作
1 u v d 表示将路径 (u,v) 加d
2 u v 表示询问路径 (u,v) 上点权绝对值的和
想了半天不会做……
搜了发题解
因为d非负,所以最多n次有一个从负数变成正数,那么用线段树记录一下区间中最大的负数,当这个最大负数加上d后变成正数的时候,继续往下update,因为最多只会有n次,所以复杂度也是nlogn级别的
#include <cstdio>#include <iostream>#include <algorithm>#define N 100010#define V E[i].tusing namespace std;typedef long long ll;ll n,m,u,v,cnt,g,op,x;int A[N],G[N],fa[N],top[N],match[N],p[N],dpt[N],size[N],son[N];struct edge{ int t,nx;}E[N<<1];struct seg{ int l,r,sum0,sum1; ll Min,Max,x,flg;}T[N<<2];inline void reaD(int &x){ char c=getchar(); x=0; int f=1; for(;c>57||c<48;c=getchar())if(c=='-') f=-1; for(;c>=48&&c<=57;x=x*10+c-48,c=getchar());x*=f;}inline void reaD(ll &x){ char c=getchar(); x=0; int f=1; for(;c>57||c<48;c=getchar()) if(c=='-') f=-1; for(;c>=48&&c<=57;x=x*10+c-48,c=getchar()); x*=f;}inline void add(int x,int y){ E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt; E[++cnt].t=x; E[cnt].nx=G[y]; G[y]=cnt;}void dfs0(int x,int f){ fa[x]=f; dpt[x]=dpt[f]+1; size[x]=1; for(int i=G[x];i;i=E[i].nx) if(V!=f){ dfs0(V,x); if(size[V]>size[son[x]]) son[x]=V; size[x]+=size[V]; }}void dfs1(int x,int t){ p[match[x]=++g]=x; top[x]=t; if(son[x]) dfs1(son[x],t); for(int i=G[x];i;i=E[i].nx) if(V!=fa[x]&&V!=son[x]) dfs1(V,V);}inline void updat(int g){ T[g].x=T[g<<1].x+T[g<<1|1].x; T[g].sum0=T[g<<1].sum0+T[g<<1|1].sum0; T[g].sum1=T[g<<1].sum1+T[g<<1|1].sum1; T[g].Max=-(1<<30); if(T[g<<1].sum0) T[g].Max=T[g<<1].Max; if(T[g<<1|1].sum0) T[g].Max=max(T[g].Max,T[g<<1|1].Max);}inline ll Abs(ll x){ return x<0?-x:x;}void Build(int g,int l,int r){ T[g].l=l; T[g].r=r; if(l==r){ if(A[p[l]]<0) T[g].sum0=1,T[g].Max=A[p[l]],T[g].x=-A[p[l]]; else T[g].sum1=1,T[g].x=A[p[l]]; return ; } int mid=l+r>>1; Build(g<<1,l,mid); Build(g<<1|1,mid+1,r); updat(g);}inline void pushdown(int g){ if(T[g].flg){ if(!T[g<<1].sum0) T[g<<1].x+=T[g].flg*(T[g<<1].r-T[g<<1].l+1); else T[g<<1].x+=T[g].flg*(T[g<<1].r-T[g<<1].l+1-T[g<<1].sum0*2); if(!T[g<<1|1].sum0) T[g<<1|1].x+=T[g].flg*(T[g<<1|1].r-T[g<<1|1].l+1); else T[g<<1|1].x+=T[g].flg*(T[g<<1|1].r-T[g<<1|1].l+1-T[g<<1|1].sum0*2); T[g<<1].Max+=T[g].flg; T[g<<1|1].Max+=T[g].flg; T[g<<1].flg+=T[g].flg; T[g<<1|1].flg+=T[g].flg; T[g].flg=0; }}void update(int g,int l,int r,int x){ if(T[g].l==T[g].r){ if(!T[g].sum0) T[g].x+=x; else if(T[g].Max+x<0) T[g].Max+=x,T[g].x-=x; else T[g].sum0=0,T[g].sum1=1,T[g].x=T[g].Max+x; return ; } if(T[g].l==l&&T[g].r==r){ if(!T[g].sum0){ T[g].x+=1ll*x*(T[g].r-T[g].l+1); T[g].flg+=x; return ; } if(T[g].Max+x<0){ T[g].Max+=x; T[g].x+=1ll*(T[g].r-T[g].l+1-T[g].sum0*2)*x; T[g].flg+=x; return ; } } pushdown(g); int mid=T[g].l+T[g].r>>1; if(r<=mid) update(g<<1,l,r,x); else if(l>mid) update(g<<1|1,l,r,x); else update(g<<1,l,mid,x),update(g<<1|1,mid+1,r,x); updat(g);}inline void update(int u,int v,int x){ while(top[u]!=top[v]){ if(dpt[top[u]]<dpt[top[v]]) swap(u,v); update(1,match[top[u]],match[u],x); u=fa[top[u]]; } if(dpt[u]<dpt[v]) swap(u,v); update(1,match[v],match[u],x);}ll query(int g,int l,int r){ if(T[g].l==l&&T[g].r==r) return T[g].x; pushdown(g); int mid=T[g].l+T[g].r>>1; if(r<=mid) return query(g<<1,l,r); if(l>mid) return query(g<<1|1,l,r); return query(g<<1,l,mid)+query(g<<1|1,mid+1,r);}inline ll query(int u,int v){ ll r=0; while(top[u]!=top[v]){ if(dpt[top[u]]<dpt[top[v]]) swap(u,v); r+=query(1,match[top[u]],match[u]); u=fa[top[u]]; } if(dpt[u]<dpt[v]) swap(u,v); return r+query(1,match[v],match[u]);}int main(){ freopen("4127.in","r",stdin); freopen("4127.out","w",stdout); reaD(n); reaD(m); for(int i=1;i<=n;i++) reaD(A[i]); for(int i=1;i<n;i++) reaD(u),reaD(v),add(u,v); dfs0(1,0); dfs1(1,1); Build(1,1,g); for(int i=1;i<=m;i++){ reaD(op); if(op==1){ reaD(u); reaD(v); reaD(x); update(u,v,x); } else{ reaD(u); reaD(v); printf("%lld\n",query(u,v)); } } return 0;}
0 0
- [BZOJ4127][树链剖分][线段树][乱搞]Abs
- 【bzoj4127】Abs 线段树+树链剖分
- BZOJ4127 Abs (树链剖分 线段树)
- [BZOJ4127]Abs(树链剖分)
- 【BZOJ4127】Abs
- bzoj 4127: Abs(树链剖分+线段树)
- [树链剖分 线段树] BZOJ 4127 Abs
- bzoj 4127: Abs(树链剖分+线段树)
- codeforces 444C DZY Loves Colors 线段树乱搞
- 【 bzoj 4355 】 Play with sequence - 线段树乱搞
- BZOJ-3225 立方体覆盖 线段树+扫描线+乱搞
- [NOIP模拟题][数学][乱搞][DP?][扫描线][线段树]
- BZOJ 3922: Karin的弹幕 线段树 暴力乱搞
- BZOJ 4127 Abs 树链剖分
- 【BZOJ 4127】Abs 树链剖分
- ABS
- abs
- abs
- VC++电子书
- LintCode : x的平方根
- xdu_1064:Desolator in RA2
- 解决java compiler level does not match the version of the installed java project facet
- Number of Segments in a String
- [BZOJ4127][树链剖分][线段树][乱搞]Abs
- web_2017.03.02
- 数据库主从复制的原理
- WebService(2):注解详解
- Ubuntu 16 MATLAB2015b安装 (以及虚拟机扩内存)
- Android开发——Volley的使用详解
- Ancient Cipher UVA
- window+mysql5.7打开二进制日志开关
- linux 更新系统时间