[loj3325]区间和

关于修改,通过segment tree beats不妨转换为"将区间内的最小值均加上$x\ge 0$"

关于询问,通常即维护最大前缀/后缀/子段和,但显然无法对其直接打上述操作的懒标记

维护一个阈值$x_{\min}$,表示当且仅当$x\ge x_{\min}$时其子树内会发生某个信息的修改

关于$x_{\min}$的push-up,对(初始)所维护的信息均记录对应区间内最小值的数量即可

此时,仅在$x\ge x_{\min}$时进行递归,并分析此做法的复杂度——

定义节点的势能为其最大前缀/后缀和的长度+最大子段所选的在3种方式中最小值数量的排名

定义整颗线段树的势能为$\log n\cdot $所有节点势能和,并对节点分类讨论:

1.对于递归经过且不被完全覆盖的节点,前者单调不降,后者至多增加$o(\log^{2}n)$的势能

2.对于递归经过且被完全覆盖的节点,两者均单调不降

3.对于递归经过的叶子,其必然会减少$o(\log n)$的势能,即与第2步的递归抵消

同时,势能的范围为$[0,n\log^{2}n]$,总复杂度为$o(n\log^{2}n+m\log^{2}n)$,可以通过

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 100005
  4 #define ll long long
  5 #define L (k<<1)
  6 #define R (L+1)
  7 #define mid (l+r>>1)
  8 struct Seg{
  9     int l,r,cnt;
 10     ll sum;
 11     bool operator < (const Seg &k)const{
 12         return (sum<k.sum)||(sum==k.sum)&&(cnt<k.cnt);
 13     }
 14 };
 15 struct Data{
 16     int mn,cmn,xmin;
 17     Seg sum,pre,suf,ans;
 18     Data(){}
 19     Data(int l,ll x){
 20         mn=x,cmn=1e9,xmin=2e9;
 21         sum=pre=suf=ans=sum=Seg{l,l,1,x};
 22     }
 23 }f[N<<2];
 24 int n,m,p,l,r,x,a[N],tag[N<<2];
 25 void add(Seg &k,int x){
 26     k.sum+=(ll)x*k.cnt;
 27 }
 28 Seg add(Seg x,Seg y){
 29     return Seg{x.l,y.r,x.cnt+y.cnt,x.sum+y.sum};
 30 }
 31 int get_nex(Seg x,Seg y){
 32     return min(1.0*(x.sum-y.sum)/(y.cnt-x.cnt),2e9);
 33 }
 34 void upd(int k,int x){
 35     tag[k]+=x,f[k].mn+=x,f[k].xmin-=x;
 36     add(f[k].sum,x),add(f[k].pre,x),add(f[k].suf,x),add(f[k].ans,x);
 37 }
 38 void down(int k){
 39     if (tag[k]){
 40         if (f[L].mn+tag[k]==f[k].mn)upd(L,tag[k]);
 41         if (f[R].mn+tag[k]==f[k].mn)upd(R,tag[k]);
 42         tag[k]=0;
 43     }
 44 }
 45 Data merge(Data x,Data y){
 46     Data ans;
 47     if (x.mn>y.mn)x.sum.cnt=x.pre.cnt=x.suf.cnt=x.ans.cnt=0;
 48     if (x.mn<y.mn)y.sum.cnt=y.pre.cnt=y.suf.cnt=y.ans.cnt=0;
 49     ans.mn=min(x.mn,y.mn),ans.cmn=min(x.cmn,y.cmn);
 50     if (x.mn!=ans.mn)ans.cmn=min(ans.cmn,x.mn);
 51     if (y.mn!=ans.mn)ans.cmn=min(ans.cmn,y.mn);
 52     ans.xmin=min(x.xmin,y.xmin),ans.sum=add(x.sum,y.sum);
 53     Seg op=add(x.sum,y.pre),os=add(x.suf,y.sum),oa=add(x.suf,y.pre);
 54     ans.pre=max(x.pre,op),ans.suf=max(y.suf,os),ans.ans=max(max(x.ans,y.ans),oa);
 55     if (ans.pre.cnt<x.pre.cnt)ans.xmin=min(ans.xmin,get_nex(ans.pre,x.pre));
 56     if (ans.pre.cnt<op.cnt)ans.xmin=min(ans.xmin,get_nex(ans.pre,op));
 57     if (ans.suf.cnt<y.suf.cnt)ans.xmin=min(ans.xmin,get_nex(ans.suf,y.suf));
 58     if (ans.suf.cnt<os.cnt)ans.xmin=min(ans.xmin,get_nex(ans.suf,os));
 59     if (ans.ans.cnt<x.ans.cnt)ans.xmin=min(ans.xmin,get_nex(ans.ans,x.ans));
 60     if (ans.ans.cnt<y.ans.cnt)ans.xmin=min(ans.xmin,get_nex(ans.ans,y.ans));
 61     if (ans.ans.cnt<oa.cnt)ans.xmin=min(ans.xmin,get_nex(ans.ans,oa));
 62     return ans;
 63 }
 64 void build(int k,int l,int r){
 65     if (l==r){
 66         f[k]=Data(l,a[l]);
 67         return;
 68     }
 69     build(L,l,mid),build(R,mid+1,r);
 70     f[k]=merge(f[L],f[R]);
 71 }
 72 void update(int k,int l,int r,int x,int y,int z){
 73     if ((l>y)||(x>r)||(f[k].mn>=z))return;
 74     if ((x<=l)&&(r<=y)){
 75         if ((z<f[k].cmn)&&(z-f[k].mn<f[k].xmin)){
 76             upd(k,z-f[k].mn);
 77             return;
 78         }
 79     }
 80     down(k);
 81     update(L,l,mid,x,y,z);
 82     update(R,mid+1,r,x,y,z);
 83     f[k]=merge(f[L],f[R]);
 84 }
 85 Data query(int k,int l,int r,int x,int y){
 86     if ((x<=l)&&(r<=y))return f[k];
 87     down(k);
 88     if (y<=mid)return query(L,l,mid,x,y);
 89     if (mid<x)return query(R,mid+1,r,x,y);
 90     return merge(query(L,l,mid,x,y),query(R,mid+1,r,x,y));
 91 }
 92 int main(){
 93     scanf("%d%d",&n,&m);
 94     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
 95     build(1,1,n);
 96     for(int i=1;i<=m;i++){
 97         scanf("%d%d%d",&p,&l,&r);
 98         if (!p){
 99             scanf("%d",&x);
100             update(1,1,n,l,r,x);
101         }
102         if (p)printf("%lld\n",max(query(1,1,n,l,r).ans.sum,0LL));
103     }
104     return 0;
105 }
View Code

 

posted @ 2022-03-03 13:56  PYWBKTDA  阅读(51)  评论(0编辑  收藏  举报