P6792 [SNOI2020] 区间和

根据小白逛公园的思想,区间 \([l,r]\) 维护 \(lx,rx,mx\) 分别表示必须包含左或右端点的最大子段和,当前整个区间的最大子段和。

吉司机 + KTT,每个节点维护三个函数 \(y=kx+b\) 分别为区间三种最大子段和。\(k\) 为三种最大子段和所对子段包含区间最小值的数量。\(b\) 为三种最大子段和当前的值,对于区间 \([l,r]\),每次修改相当于 \(x\)\(d-mn\),其中 \(mn\) 为区间最小值。\(itr\) 要考虑三种最大子段和每一种的更新。

有一个需要注意,在取到最大子段和的前提下要使子段包含区间最小值数量尽量多 (斜率越大增长越快)。

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
#define int long long
const int N=2e5+5;
const ll inf=2e18;ll a[N];
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read(){int x=0,f=1;char ch=nc();
    while(ch<48||ch>57){if(ch=='-')f=-1;ch=nc();}
    while(ch>=48&&ch<=57)x=x*10+ch-48,ch=nc();
   	return x*f;
}
struct node{int l,r,le,re,me,c;ll lx,rx,mx,s,itr,laz,mn,mn1;}tr[N<<1];
ll dv(ll x,ll y){return (y<=0?inf:(x+y-1)/y);}
ll get(ll x,ll y,ll lx,ll ly){return (x>y?dv(x-y,ly-lx):dv(y-x,lx-ly));}
struct mxd{ll l,r,m,s;};
void pushup(int u){ll itr;
	tr[u].mn=min(tr[u<<1].mn,tr[u<<1|1].mn),tr[u].c=0;
	if(tr[u].mn==tr[u<<1].mn)tr[u].c+=tr[u<<1].c;if(tr[u].mn==tr[u<<1|1].mn)tr[u].c+=tr[u<<1|1].c;
	if(tr[u<<1].mn^tr[u<<1|1].mn)tr[u].mn1=min(max(tr[u<<1].mn,tr[u<<1|1].mn),min(tr[u<<1].mn1,tr[u<<1|1].mn1));
	else tr[u].mn1=min(tr[u<<1].mn1,tr[u<<1|1].mn1);
	tr[u].itr=min(tr[u<<1].itr,tr[u<<1|1].itr);
	if(tr[u].itr<=0)tr[u].itr=inf;
	itr=get(tr[u<<1].lx,tr[u<<1].s+tr[u<<1|1].lx,(tr[u<<1].mn==tr[u].mn?tr[u<<1].le:0),(tr[u<<1].mn==tr[u].mn?tr[u<<1].c:0)+(tr[u<<1|1].mn==tr[u].mn?tr[u<<1|1].le:0));
	if(itr<=0)itr=inf;tr[u].itr=min(tr[u].itr,itr);
	itr=get(tr[u<<1|1].rx,tr[u<<1|1].s+tr[u<<1].rx,(tr[u<<1|1].mn==tr[u].mn?tr[u<<1|1].re:0),(tr[u<<1|1].mn==tr[u].mn?tr[u<<1|1].c:0)+(tr[u<<1].mn==tr[u].mn?tr[u<<1].re:0));
	if(itr<=0)itr=inf;tr[u].itr=min(tr[u].itr,itr);
	itr=get(tr[u<<1].mx,tr[u<<1|1].mx,(tr[u<<1].mn==tr[u].mn?tr[u<<1].me:0),(tr[u<<1|1].mn==tr[u].mn?tr[u<<1|1].me:0));
	if(itr<=0)itr=inf;tr[u].itr=min(tr[u].itr,itr);
	ll mx=max(tr[u<<1].mx,tr[u<<1|1].mx);int len=max((mx==tr[u<<1].mx?(tr[u].mn==tr[u<<1].mn?tr[u<<1].me:0):0),(mx==tr[u<<1|1].mx?(tr[u<<1|1].mn==tr[u].mn?tr[u<<1|1].me:0):0));
	itr=get(mx,tr[u<<1].rx+tr[u<<1|1].lx,len,(tr[u<<1].mn==tr[u].mn?tr[u<<1].re:0)+(tr[u<<1|1].mn==tr[u].mn?tr[u<<1|1].le:0));
	if(itr<=0)itr=inf;tr[u].itr=min(tr[u].itr,itr);
	tr[u].lx=max(tr[u<<1].lx,tr[u<<1].s+tr[u<<1|1].lx),
	tr[u].rx=max(tr[u<<1|1].rx,tr[u<<1|1].s+tr[u<<1].rx),
	tr[u].mx=max(max(tr[u<<1].mx,tr[u<<1|1].mx),tr[u<<1].rx+tr[u<<1|1].lx);
	tr[u].le=max((tr[u].lx==tr[u<<1].lx?(tr[u<<1].mn==tr[u].mn?tr[u<<1].le:0):0),
				(tr[u].lx==tr[u<<1].s+tr[u<<1|1].lx?(tr[u<<1].mn==tr[u].mn?tr[u<<1].c:0)+(tr[u<<1|1].mn==tr[u].mn?tr[u<<1|1].le:0):0)),
	tr[u].re=max((tr[u].rx==tr[u<<1|1].rx?(tr[u<<1|1].mn==tr[u].mn?tr[u<<1|1].re:0):0),
				(tr[u].rx==tr[u<<1|1].s+tr[u<<1].rx?(tr[u<<1|1].mn==tr[u].mn?tr[u<<1|1].c:0)+(tr[u<<1].mn==tr[u].mn?tr[u<<1].re:0):0)),
	tr[u].me=max(max((tr[u].mx==tr[u<<1].mx?(tr[u<<1].mn==tr[u].mn?tr[u<<1].me:0):0),
				(tr[u].mx==tr[u<<1|1].mx?(tr[u<<1|1].mn==tr[u].mn?tr[u<<1|1].me:0):0)),
				(tr[u].mx==tr[u<<1].rx+tr[u<<1|1].lx?(tr[u<<1].mn==tr[u].mn?tr[u<<1].re:0)+(tr[u<<1|1].mn==tr[u].mn?tr[u<<1|1].le:0):0));
	tr[u].s=tr[u<<1].s+tr[u<<1|1].s;
}
void pd(int u){
	ll d=max(tr[u].laz-tr[u<<1].mn,0ll),d1=max(tr[u].laz-tr[u<<1|1].mn,0ll);
	tr[u<<1].itr-=d,tr[u<<1|1].itr-=d1;
	tr[u<<1].mx+=d*tr[u<<1].me,tr[u<<1|1].mx+=d1*tr[u<<1|1].me,
	tr[u<<1].lx+=d*tr[u<<1].le,tr[u<<1|1].lx+=d1*tr[u<<1|1].le,
	tr[u<<1].rx+=d*tr[u<<1].re,tr[u<<1|1].rx+=d1*tr[u<<1|1].re,
	tr[u<<1].mn=max(tr[u<<1].mn,tr[u].laz),tr[u<<1|1].mn=max(tr[u<<1|1].mn,tr[u].laz),
	tr[u<<1].s+=tr[u<<1].c*d,tr[u<<1|1].s+=tr[u<<1|1].c*d1, 
	tr[u<<1].laz=max(tr[u<<1].laz,tr[u].laz),tr[u<<1|1].laz=max(tr[u<<1|1].laz,tr[u].laz),tr[u].laz=-inf;
}
void build(int u,int l,int r){tr[u]={l,r},tr[u].laz=-inf;
	if(l==r)return tr[u]={l,r,1,1,1,1,a[l],a[l],a[l],a[l],inf,-inf,a[l],inf},void();
	int mid=l+r>>1;build(u<<1,l,mid),build(u<<1|1,mid+1,r);pushup(u);
//	cout<<tr[u].l<<' '<<tr[u].r<<' '<<tr[u].lx<<' '<<tr[u].rx<<' '<<tr[u].mx<<' '<<tr[u].le<<' '<<tr[u].re<<' '<<tr[u].me<<' '<<tr[u].mn<<' '<<tr[u].mn1<<endl;
}
void rebuild(int u,int l,int r){
	if(l==r){ll d=max(a[l],tr[u].laz);
		return tr[u]={l,r,1,1,1,1,d,d,d,d,inf,tr[u].laz,d,inf},void();
	}if(tr[u].itr>0)return;int mid=l+r>>1;pd(u);rebuild(u<<1,l,mid),rebuild(u<<1|1,mid+1,r);pushup(u);
//	cout<<tr[u].l<<' '<<tr[u].r<<' '<<tr[u].lx<<' '<<tr[u].rx<<' '<<tr[u].mx<<' '<<tr[u].le<<' '<<tr[u].re<<' '<<tr[u].me<<' '<<tr[u].mn<<' '<<tr[u].mn1<<endl;
}
void add(int u,int l,int r,ll x){
	if(tr[u].l>=l&&tr[u].r<=r&&tr[u].mn<x&&tr[u].mn1>x){ll d=x-tr[u].mn;
		tr[u].s+=d*tr[u].c,tr[u].laz=max(tr[u].laz,x),tr[u].itr-=d,
		tr[u].mx+=tr[u].me*d,tr[u].lx+=tr[u].le*d,tr[u].rx+=tr[u].re*d,tr[u].mn=x;
		if(tr[u].itr<=0)rebuild(u,tr[u].l,tr[u].r);return;
//		cout<<tr[u].l<<' '<<tr[u].r<<' '<<tr[u].lx<<' '<<tr[u].rx<<' '<<tr[u].mx<<' '<<tr[u].le<<' '<<tr[u].re<<' '<<tr[u].me<<' '<<tr[u].mn<<' '<<tr[u].mn1<<endl;return;
	}
//	cout<<'*'<<tr[u].l<<' '<<tr[u].r<<' '<<tr[u].mn<<' '<<tr[u].mn1<<endl;
	int mid=tr[u].l+tr[u].r>>1;if(tr[u].l==tr[u].r||tr[u].mn>=x)return;pd(u);
	if(l<=mid)add(u<<1,l,r,x);if(r>mid)add(u<<1|1,l,r,x);pushup(u);
}
mxd query(int u,int l,int r){
	if(tr[u].l>=l&&tr[u].r<=r)return mxd{tr[u].lx,tr[u].rx,tr[u].mx,tr[u].s};pd(u);
	int mid=tr[u].l+tr[u].r>>1;mxd lf={-inf,-inf,-inf,0},rt={-inf,-inf,-inf,0};
	if(l>mid)return query(u<<1|1,l,r);if(r<=mid)return query(u<<1,l,r);
	if(l<=mid)lf=query(u<<1,l,r);if(r>mid)rt=query(u<<1|1,l,r);
	return mxd{max(lf.l,lf.s+rt.l),max(rt.r,rt.s+lf.r),max(max(rt.m,lf.m),rt.l+lf.r),lf.s+rt.s};
}
signed main(){
//	freopen("tst.in","r",stdin);	
//	freopen("1.out","w",stdout);
//	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	int n,q;n=read(),q=read();
	for(int i=1;i<=n;i++)a[i]=read();build(1,1,n);
	while(q--){int op,l,r,x;op=read(),l=read(),r=read();
		if(!op)x=read(),add(1,l,r,x);
		else printf("%lld\n",max(0ll,query(1,l,r).m));
	}
	return 0;
}
posted @ 2025-10-16 09:51  Uesugi1  阅读(7)  评论(0)    收藏  举报