#线段树#UOJ 164【清华集训2015】V

题目传送门


分析

可以发现,三种操作均能被表示为 \(w=max(w+a,b)\) 的形式,

其中 \((a,b)=(x,-inf),(-x,0),(-inf,x)\),既然要求历史最大值,

那么就要同时维护当前以及历史的四个懒标记(\(a\) 和 \(b\)),主要是转移比较麻烦。


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
typedef long long lll; const lll inf=1e18;
const int N=500011; lll a[N]; int n,m;
int iut(){
	int ans=0,f=1; char c=getchar();
	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans*f;
}
void print(lll ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
struct Segment_Tree{
	lll mx[N<<2][2],lazy1[N<<2][2],lazy2[N<<2][2];
	lll Plus(lll x,lll y){
		if (x==-inf||y==-inf) return -inf;
		return x+y;
	}
	void Clear_Lazy(int k){
		lazy1[k][0]=0;
		lazy1[k][1]=lazy2[k][0]=lazy2[k][1]=-inf;
	}
	void pup(int k){
		mx[k][0]=max(mx[k<<1][0],mx[k<<1|1][0]);
		mx[k][1]=max(mx[k<<1][1],mx[k<<1|1][1]);
	}
	void ptag(int k,lll z,lll Z,lll w,lll W){
		mx[k][1]=max(mx[k][1],max(Plus(mx[k][0],Z),W));
		lazy1[k][1]=max(lazy1[k][1],Plus(lazy1[k][0],Z));
		lazy2[k][1]=max(lazy2[k][1],max(Plus(lazy2[k][0],Z),W));
		mx[k][0]=max(Plus(mx[k][0],z),w);
		lazy1[k][0]=Plus(lazy1[k][0],z);
		lazy2[k][0]=max(Plus(lazy2[k][0],z),w);
	}
	void pdown(int k){
		if (lazy1[k][0]==0&&lazy1[k][1]==-inf&&lazy2[k][0]==-inf&&lazy2[k][1]==-inf) return;
		ptag(k<<1,lazy1[k][0],lazy1[k][1],lazy2[k][0],lazy2[k][1]);
		ptag(k<<1|1,lazy1[k][0],lazy1[k][1],lazy2[k][0],lazy2[k][1]);
		Clear_Lazy(k);
	}
	void build(int k,int l,int r){
		Clear_Lazy(k);
		if (l==r){
			mx[k][0]=mx[k][1]=a[l];
			return;
		}
		int mid=(l+r)>>1;
		build(k<<1,l,mid);
		build(k<<1|1,mid+1,r);
		pup(k);
	}
	void update(int k,int l,int r,int x,int y,lll z,lll w){
		if (l==x&&r==y){
			ptag(k,z,z,w,w);
			return;
		}
		int mid=(l+r)>>1;
		pdown(k);
		if (y<=mid) update(k<<1,l,mid,x,y,z,w);
		else if (x>mid) update(k<<1|1,mid+1,r,x,y,z,w);
			else update(k<<1,l,mid,x,mid,z,w),update(k<<1|1,mid+1,r,mid+1,y,z,w);
		pup(k);
	}
	lll query(int k,int l,int r,int x,int y,int t){
		if (l==x&&r==y) return mx[k][t];
		int mid=(l+r)>>1;
		pdown(k);
		if (y<=mid) return query(k<<1,l,mid,x,y,t);
		else if (x>mid) return query(k<<1|1,mid+1,r,x,y,t);
			else return max(query(k<<1,l,mid,x,mid,t),query(k<<1|1,mid+1,r,mid+1,y,t));
	}
}Tre;
int main(){
	n=iut(),m=iut();
	for (int i=1;i<=n;++i) a[i]=iut();
	Tre.build(1,1,n);
	for (int i=1;i<=m;++i){
		int opt=iut(),l=iut();
		if (opt<4){
			int r=iut(),z=iut();
			if (opt==1) Tre.update(1,1,n,l,r,z,-inf);
			else if (opt==2) Tre.update(1,1,n,l,r,-z,0);
				else Tre.update(1,1,n,l,r,-inf,z);
		}else print(Tre.query(1,1,n,l,l,opt-4)),putchar(10);
	}
	return 0;
}
posted @ 2026-10-14 11:56  lemondinosaur  阅读(5)  评论(0)    收藏  举报