[uoj164]V
记$a_{i}$为当前第$i$个水箱的电流,$b_{i}$为$a_{i}$的历史最大值
不难发现,问题即要支持:对$a_{i}$区间覆盖和区间加(并对0取$\max$);查询某个$a_{i}$和$b_{i}$
整体思路类似于bzoj3064,仍维护$\max a,b$和操作序列,操作执行方式即令
$$
\begin{cases}\max a=x,\max b=\max(\max b,\max a)&(覆盖操作)\\\max a=\max(\max a+x,0),\max b=\max(\max b,\max a)&(加操作)\end{cases}
$$
维护的信息也是类似地,只需要重新定义"和",并将第一个信息的两个值均用与$\max a$有关的函数形式存储,那么同样也可以合并
考虑函数的形式,对两者分别讨论:
1.第一个值的函数仅取决于最小前缀和和整个序列的和,并且可以合并
2.第二个值的函数仅取决于最大前缀和、最大子段和,并且需要再维护最大后缀和(即整个序列的和-最小前缀和)来支持合并
具体合并方式可以根据定义得到或参考代码,这里省略
(不难发现也是可以支持区间查询$a_{i}$和$b_{i}$最大值的)
时间复杂度为$o(m\log n)$,可以通过

1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 500005 4 #define ll long long 5 #define L (k<<1) 6 #define R (L+1) 7 #define mid (l+r>>1) 8 struct Data{ 9 ll s1,mx1,mn1,mx,p,s2,mx2,Mx; 10 }tag[N<<2]; 11 int n,m,p,x,y,z,leaf[N<<2]; 12 ll a[N<<2],b[N<<2]; 13 void upd(int k,Data x){ 14 if (leaf[k]==1){ 15 b[k]=max(b[k],max(max(a[k]+x.mx1,x.mx),x.Mx)); 16 if (x.p)a[k]=x.s2; 17 else a[k]=max(a[k],-x.mn1)+x.s1; 18 } 19 if (tag[k].p){ 20 tag[k].mx2=max(tag[k].mx2,max(tag[k].s2+x.mx1,x.mx)); 21 tag[k].Mx=max(tag[k].Mx,max(tag[k].s2+x.mx1,x.mx)); 22 tag[k].s2=max(tag[k].s2,-x.mn1)+x.s1; 23 } 24 else{ 25 tag[k].mx=max(tag[k].mx,max(tag[k].s1-tag[k].mn1+x.mx1,x.mx)); 26 tag[k].mn1=min(tag[k].mn1,tag[k].s1+x.mn1); 27 tag[k].mx1=max(tag[k].mx1,tag[k].s1+x.mx1); 28 tag[k].s1+=x.s1; 29 } 30 if (x.p){ 31 tag[k].p=1,tag[k].s2=x.s2,tag[k].mx2=x.mx2; 32 tag[k].Mx=max(tag[k].Mx,x.Mx); 33 } 34 } 35 void down(int k){ 36 upd(L,tag[k]); 37 upd(R,tag[k]); 38 tag[k]=Data{0,0,0,0,0,0,(ll)-1e18,(ll)-1e18}; 39 } 40 void build(int k,int l,int r){ 41 leaf[k]=0; 42 tag[k]=Data{0,0,0,0,0,0,(ll)-1e18,(ll)-1e18}; 43 if (l==r){ 44 leaf[k]=1; 45 scanf("%lld",&a[k]); 46 b[k]=a[k]; 47 return; 48 } 49 build(L,l,mid); 50 build(R,mid+1,r); 51 } 52 void update(int k,int l,int r,int x,int y,Data z){ 53 if ((l>y)||(x>r))return; 54 if ((x<=l)&&(r<=y)){ 55 upd(k,z); 56 return; 57 } 58 down(k); 59 update(L,l,mid,x,y,z); 60 update(R,mid+1,r,x,y,z); 61 } 62 ll query_a(int k,int l,int r,int x){ 63 if (l==r)return a[k]; 64 down(k); 65 if (x<=mid)return query_a(L,l,mid,x); 66 return query_a(R,mid+1,r,x); 67 } 68 ll query_b(int k,int l,int r,int x){ 69 if (l==r)return b[k]; 70 down(k); 71 if (x<=mid)return query_b(L,l,mid,x); 72 return query_b(R,mid+1,r,x); 73 } 74 int main(){ 75 scanf("%d%d",&n,&m); 76 build(1,1,n); 77 for(int i=1;i<=m;i++){ 78 scanf("%d%d",&p,&x); 79 if (p==1){ 80 scanf("%d%d",&y,&z); 81 update(1,1,n,x,y,Data{z,z,0,z,0,0,0,(ll)-1e18}); 82 } 83 if (p==2){ 84 scanf("%d%d",&y,&z); 85 update(1,1,n,x,y,Data{-z,0,-z,0,0,0,0,(ll)-1e18}); 86 } 87 if (p==3){ 88 scanf("%d%d",&y,&z); 89 update(1,1,n,x,y,Data{0,0,0,0,1,z,z,z}); 90 } 91 if (p==4)printf("%lld\n",query_a(1,1,n,x)); 92 if (p==5)printf("%lld\n",query_b(1,1,n,x)); 93 } 94 return 0; 95 }