Kinetic Tournament Tree (KTT) 维护区间加正数、求区间最大连续子段和

#include<stdio.h>
#include<algorithm>
#include<utility>
typedef long long ll;
const int N=4e5+5;
const ll inf=1e18;
struct line{
	ll k,b;
	line(ll _k=0,ll _b=0):k(_k),b(_b){}
	line operator + (const line &x) const{return line(k+x.k,b+x.b);}
	void add(ll x){b+=k*x;}
};
auto max = [](line a,line b) -> std::pair<line,ll> {
	if(a.k<b.k||(a.k==b.k&&a.b<b.b)) std::swap(a,b);
	return a.b>=b.b? std::make_pair(a,inf):std::make_pair(b,(b.b-a.b)/(a.k-b.k));
};
struct ktt{
	line sum,lmax,rmax,totmax;
	ll x,lazy;
	ktt(line _sum=line(),line _lmax=line(),line _rmax=line(),line _totmax=line(),ll _x=0,ll _lazy=0):sum(_sum),lmax(_lmax),rmax(_rmax),totmax(_totmax),x(_x),lazy(_lazy){}
	ktt operator + (const ktt &a) const{
		ktt res;
		std::pair<line,ll> tmp;
		res.x=std::min(x,a.x);
		res.sum=sum+a.sum;
		tmp=max(lmax,sum+a.lmax);
		res.lmax=tmp.first;
		res.x=std::min(res.x,tmp.second);
		tmp=max(a.rmax,rmax+a.sum);
		res.rmax=tmp.first;
		res.x=std::min(res.x,tmp.second);
		tmp=max(totmax,a.totmax);
		res.x=std::min(res.x,tmp.second);
		tmp=max(tmp.first,rmax+a.lmax);
		res.totmax=tmp.first;
		res.x=std::min(res.x,tmp.second);
		return res;
	}
}s[N<<2];
int n,m;
ll a[N];
auto pushup = [](int k) -> void {
	ktt res=s[k<<1]+s[k<<1|1];
	res.lazy=s[k].lazy;
	s[k]=res;
};
auto addtag = [](int k,ll val) -> void {
	s[k].lazy+=val;
	s[k].sum.add(val);
	s[k].lmax.add(val);
	s[k].rmax.add(val);
	s[k].totmax.add(val);
	s[k].x-=val;
};
auto pushdown = [](int k) -> void {
	if(s[k].lazy!=0){
		addtag(k<<1,s[k].lazy);
		addtag(k<<1|1,s[k].lazy);
		s[k].lazy=0;
	}
};
auto re = [](auto &&self,int k,ll val) -> void {
	if(val>s[k].x){
		val+=s[k].lazy,s[k].lazy=0;
		self(self,k<<1,val),self(self,k<<1|1,val);
		pushup(k);
	}
	else addtag(k,val);
};
auto build = [](auto &&self,int k,int l,int r) -> void {
	if(l==r){s[k]=ktt(line(1,a[l]),line(1,a[l]),line(1,a[l]),line(1,a[l]),inf,0);return;}
	int mid=l+(r-l>>1);
	self(self,k<<1,l,mid),self(self,k<<1|1,mid+1,r);
	pushup(k);	
};
auto change = [](auto &&self,int k,int l,int r,int x,int y,ll val) -> void {
	if(x<=l&&r<=y){re(re,k,val);return;}
	pushdown(k);
	int mid=l+(r-l>>1);
	if(y<=mid) self(self,k<<1,l,mid,x,y,val);
	else if(x>mid) self(self,k<<1|1,mid+1,r,x,y,val);
	else self(self,k<<1,l,mid,x,y,val),self(self,k<<1|1,mid+1,r,x,y,val);
	pushup(k);
};
auto query = [](auto &&self,int k,int l,int r,int x,int y) -> ktt {
	if(x<=l&&r<=y) return s[k];
	pushdown(k);
	int mid=l+(r-l>>1);
	if(y<=mid) return self(self,k<<1,l,mid,x,y);
	else if(x>mid) return self(self,k<<1|1,mid+1,r,x,y);
	else return self(self,k<<1,l,mid,x,y)+self(self,k<<1|1,mid+1,r,x,y);
};
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	build(build,1,1,n);
	int opt,x,y;
	ll z;
	while(m--){
		scanf("%d",&opt);
		if(opt==1) scanf("%d%d%lld",&x,&y,&z),change(change,1,1,n,x,y,z);
		else scanf("%d%d",&x,&y),printf("%lld\n",std::max(0ll,query(query,1,1,n,x,y).totmax.b));
	}
	return 0;
}
posted @ 2025-11-05 16:01  gevenfeng  阅读(5)  评论(1)    收藏  举报