BZOJ[4127] Abs
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=4127
不算难的样子,才见过此类模型。
首先可以发现每次修改只增不减,那么这$O(n)$的负数最多只会有$n$次由负变正。
所以对于每一次由负变正我们暴力在线段树上维护,每一次由负变正在线段树上会经过$O(logn)$层。
效率$O(logn)$。
其他的维护一下区间负数的个数什么的就可以搞了。
一遍AC爽
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 #define l(x) ch[x][0] 6 #define r(x) ch[x][1] 7 #define N 100010 8 #define LL long long 9 #define INF 0x3f3f3f3f3f3f3f3fLL 10 11 using namespace std; 12 13 struct edge{ 14 int x,to; 15 }E[N<<1]; 16 17 int n,m,totE; 18 int g[N]; 19 20 inline int Abs(int x){ 21 if(x<0) return -x; 22 return x; 23 } 24 25 inline void ade(int x,int y){ 26 E[++totE]=(edge){y,g[x]}; g[x]=totE; 27 } 28 29 namespace Segtree{ 30 int tot; 31 int ch[N<<1][2]; 32 int totf[N<<1],siz[N<<1]; 33 LL maxf[N<<1],sumv[N<<1],addv[N<<1]; 34 35 void push(int x){ 36 if(!l(x)||!addv[x]) return; 37 addv[l(x)]+=addv[x]; 38 sumv[l(x)]+=addv[x]*(LL)(siz[l(x)]-2*totf[l(x)]); 39 maxf[l(x)]+=addv[x]; 40 addv[r(x)]+=addv[x]; 41 sumv[r(x)]+=addv[x]*(LL)(siz[r(x)]-2*totf[r(x)]); 42 maxf[r(x)]+=addv[x]; 43 addv[x]=0; 44 } 45 46 void up(int x){ 47 if(!l(x)) return; 48 sumv[x]=sumv[l(x)]+sumv[r(x)]; 49 maxf[x]=max(maxf[l(x)],maxf[r(x)]); 50 totf[x]=totf[l(x)]+totf[r(x)]; 51 } 52 53 void change(int x,int l,int r,int ql,int qr,int qv){ 54 push(x); 55 if(ql<=l&&r<=qr&&maxf[x]+qv<0){ 56 addv[x]+=qv; 57 sumv[x]+=qv*(LL)(siz[x]-2*totf[x]); 58 maxf[x]+=qv; 59 } 60 else if(l==r){ 61 sumv[x]=qv-sumv[x]; 62 addv[x]=0; 63 maxf[x]=-INF; 64 totf[x]=0; 65 } 66 else{ 67 int mid=(l+r)>>1; 68 if(ql<=mid) change(l(x),l,mid,ql,qr,qv); 69 if(mid<qr) change(r(x),mid+1,r,ql,qr,qv); 70 up(x); 71 } 72 } 73 74 LL ask(int x,int l,int r,int ql,int qr){ 75 push(x); 76 if(ql<=l&&r<=qr){ 77 return sumv[x]; 78 } 79 int mid=(l+r)>>1; 80 LL ans=0; 81 if(ql<=mid) ans+=ask(l(x),l,mid,ql,qr); 82 if(mid<qr) ans+=ask(r(x),mid+1,r,ql,qr); 83 up(x); 84 return ans; 85 } 86 87 int build(int src[],int l,int r){ 88 int x=++tot; 89 siz[x]=r-l+1; 90 if(l==r){ 91 sumv[x]=Abs(src[l]); 92 addv[x]=0; 93 if(src[l]>=0) maxf[x]= -INF; 94 else maxf[x]=src[l]; 95 totf[x]= (src[l]<0) ? 1:0; 96 return x; 97 } 98 int mid=(l+r)>>1; 99 l(x)=build(src,l,mid); 100 r(x)=build(src,mid+1,r); 101 up(x); 102 return x; 103 } 104 } 105 106 #define p E[i].x 107 108 int tott; 109 int L[N],a[N],fa[N],pos[N],c[N],d[N],siz[N],h[N],top[N]; 110 bool v[N]; 111 112 void dfs(int x){ 113 v[x]=1; siz[x]=1; h[x]=0; 114 for(int i=g[x];i;i=E[i].to) 115 if(!v[p]){ 116 fa[p]=x; 117 d[p]=d[x]+1; 118 dfs(p); 119 siz[x]+=siz[p]; 120 if(siz[p]>siz[h[x]]) 121 h[x]=p; 122 } 123 } 124 125 void cut(int x,int ft){ 126 L[x]=++tott; c[tott]=a[x]; pos[tott]=x; top[x]=ft; 127 if(h[x]) cut(h[x],ft); 128 for(int i=g[x];i;i=E[i].to) 129 if(p!=fa[x]&&p!=h[x]) 130 cut(p,p); 131 } 132 133 void change(int x,int y,int v){ 134 int f1=top[x],f2=top[y]; 135 while(f1!=f2){ 136 if(d[f1]<d[f2]) swap(f1,f2),swap(x,y); 137 Segtree::change(1,1,n,L[f1],L[x],v); 138 x=fa[f1]; f1=top[x]; 139 } 140 if(L[x]>L[y]) swap(x,y); 141 Segtree::change(1,1,n,L[x],L[y],v); 142 } 143 144 LL ask(int x,int y){ 145 int f1=top[x],f2=top[y]; 146 LL ans=0; 147 while(f1!=f2){ 148 if(d[f1]<d[f2]) swap(f1,f2),swap(x,y); 149 ans+=Segtree::ask(1,1,n,L[f1],L[x]); 150 x=fa[f1]; f1=top[x]; 151 } 152 if(L[x]>L[y]) swap(x,y); 153 ans+=Segtree::ask(1,1,n,L[x],L[y]); 154 return ans; 155 } 156 157 int main(){ 158 scanf("%d%d",&n,&m); 159 for(int i=1;i<=n;i++){ 160 scanf("%d",&a[i]); 161 } 162 int cmd,x,y; 163 for(int i=1;i<n;i++){ 164 scanf("%d%d",&x,&y); 165 ade(x,y); ade(y,x); 166 } 167 d[1]=1; 168 dfs(1); cut(1,1); 169 Segtree::build(c,1,n); 170 for(int i=1;i<=m;i++){ 171 int v; 172 scanf("%d%d%d",&cmd,&x,&y); 173 if(cmd==1){ 174 scanf("%d",&v); 175 change(x,y,v); 176 } 177 else printf("%lld\n",ask(x,y)); 178 } 179 return 0; 180 }