BZOJ[4127] Abs
2015-06-21 20:12
288 查看
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=4127
不算难的样子,才见过此类模型。
首先可以发现每次修改只增不减,那么这$O(n)$的负数最多只会有$n$次由负变正。
所以对于每一次由负变正我们暴力在线段树上维护,每一次由负变正在线段树上会经过$O(logn)$层。
效率$O(logn)$。
其他的维护一下区间负数的个数什么的就可以搞了。
一遍AC爽
View Code
不算难的样子,才见过此类模型。
首先可以发现每次修改只增不减,那么这$O(n)$的负数最多只会有$n$次由负变正。
所以对于每一次由负变正我们暴力在线段树上维护,每一次由负变正在线段树上会经过$O(logn)$层。
效率$O(logn)$。
其他的维护一下区间负数的个数什么的就可以搞了。
一遍AC爽
#include <cstdio> #include <cstring> #include <algorithm> #define l(x) ch[x][0] #define r(x) ch[x][1] #define N 100010 #define LL long long #define INF 0x3f3f3f3f3f3f3f3fLL using namespace std; struct edge{ int x,to; }E[N<<1]; int n,m,totE; int g ; inline int Abs(int x){ if(x<0) return -x; return x; } inline void ade(int x,int y){ E[++totE]=(edge){y,g[x]}; g[x]=totE; } namespace Segtree{ int tot; int ch[N<<1][2]; int totf[N<<1],siz[N<<1]; LL maxf[N<<1],sumv[N<<1],addv[N<<1]; void push(int x){ if(!l(x)||!addv[x]) return; addv[l(x)]+=addv[x]; sumv[l(x)]+=addv[x]*(LL)(siz[l(x)]-2*totf[l(x)]); maxf[l(x)]+=addv[x]; addv[r(x)]+=addv[x]; sumv[r(x)]+=addv[x]*(LL)(siz[r(x)]-2*totf[r(x)]); maxf[r(x)]+=addv[x]; addv[x]=0; } void up(int x){ if(!l(x)) return; sumv[x]=sumv[l(x)]+sumv[r(x)]; maxf[x]=max(maxf[l(x)],maxf[r(x)]); totf[x]=totf[l(x)]+totf[r(x)]; } void change(int x,int l,int r,int ql,int qr,int qv){ push(x); if(ql<=l&&r<=qr&&maxf[x]+qv<0){ addv[x]+=qv; sumv[x]+=qv*(LL)(siz[x]-2*totf[x]); maxf[x]+=qv; } else if(l==r){ sumv[x]=qv-sumv[x]; addv[x]=0; maxf[x]=-INF; totf[x]=0; } else{ int mid=(l+r)>>1; if(ql<=mid) change(l(x),l,mid,ql,qr,qv); if(mid<qr) change(r(x),mid+1,r,ql,qr,qv); up(x); } } LL ask(int x,int l,int r,int ql,int qr){ push(x); if(ql<=l&&r<=qr){ return sumv[x]; } int mid=(l+r)>>1; LL ans=0; if(ql<=mid) ans+=ask(l(x),l,mid,ql,qr); if(mid<qr) ans+=ask(r(x),mid+1,r,ql,qr); up(x); return ans; } int build(int src[],int l,int r){ int x=++tot; siz[x]=r-l+1; if(l==r){ sumv[x]=Abs(src[l]); addv[x]=0; if(src[l]>=0) maxf[x]= -INF; else maxf[x]=src[l]; totf[x]= (src[l]<0) ? 1:0; return x; } int mid=(l+r)>>1; l(x)=build(src,l,mid); r(x)=build(src,mid+1,r); up(x); return x; } } #define p E[i].x int tott; int L ,a ,fa ,pos ,c ,d ,siz ,h ,top ; bool v ; void dfs(int x){ v[x]=1; siz[x]=1; h[x]=0; for(int i=g[x];i;i=E[i].to) if(!v[p]){ fa[p]=x; d[p]=d[x]+1; dfs(p); siz[x]+=siz[p]; if(siz[p]>siz[h[x]]) h[x]=p; } } void cut(int x,int ft){ L[x]=++tott; c[tott]=a[x]; pos[tott]=x; top[x]=ft; if(h[x]) cut(h[x],ft); for(int i=g[x];i;i=E[i].to) if(p!=fa[x]&&p!=h[x]) cut(p,p); } void change(int x,int y,int v){ int f1=top[x],f2=top[y]; while(f1!=f2){ if(d[f1]<d[f2]) swap(f1,f2),swap(x,y); Segtree::change(1,1,n,L[f1],L[x],v); x=fa[f1]; f1=top[x]; } if(L[x]>L[y]) swap(x,y); Segtree::change(1,1,n,L[x],L[y],v); } LL ask(int x,int y){ int f1=top[x],f2=top[y]; LL ans=0; while(f1!=f2){ if(d[f1]<d[f2]) swap(f1,f2),swap(x,y); ans+=Segtree::ask(1,1,n,L[f1],L[x]); x=fa[f1]; f1=top[x]; } if(L[x]>L[y]) swap(x,y); ans+=Segtree::ask(1,1,n,L[x],L[y]); return ans; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } int cmd,x,y; for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); ade(x,y); ade(y,x); } d[1]=1; dfs(1); cut(1,1); Segtree::build(c,1,n); for(int i=1;i<=m;i++){ int v; scanf("%d%d%d",&cmd,&x,&y); if(cmd==1){ scanf("%d",&v); change(x,y,v); } else printf("%lld\n",ask(x,y)); } return 0; }
View Code
相关文章推荐
- Chromium自动为Debian用户下载了可监听语音的二进制文件
- 多线程 编写多线程的两种方式
- 个人作业--课本最后一章及博客读后感
- 归并排序和快速排序的算法实现
- 个人作业--课本最后一章及博客读后感
- CDOJ 1088 王之迷宫 BFS
- 《心理学与生活》发展与教育(上)
- UIView frame, bounds and center
- 读后感
- 电影名:东邪西毒
- FrameLayou和UI的布局优化(merge、include、ViewStub)
- 运行及总结
- 欢迎使用CSDN-markdown编辑器
- 利用随机前馈神经网络生成图像观察网络复杂度
- leetcode House Robber
- MySQL 常用运算符
- 数据结构——二叉树2(c++)
- LeetCode---(152)Maximum Product Subarray
- javascript--理解Javascript之this关键字
- 关于我自己的三个层次