UOJ #164 【清华集训2015】 V

题目链接:V

  这道题由于是单点询问,所以异常好写。

  注意到每种修改操作都可以用一个标记((a,b))表示。标记((a,b))的意义就是(x= max{x+a,b}) 

  同时这种标记也是支持合并的。有((a,b)+(c,d)=(a+c,max{b+c,d}))

  用上这种标记的话,(1)操作就是((x,0)),(2)操作就是((-x,0)),(3)操作就是((-inf,x))。

  要查询单点值的话只要把所有标记都下放了就好了。

  这种标记也支持取(max)。即,(max{(a,b),(c,d)}=(max{a,c},max{b,d}))。本质上就是一个分段函数取(max)的过程。

  所以最后一问再维护一个历史最大值这道题就做完了。注意下传标记时先传历史标记。

  还有一个要注意的地方:标记((a,b))里的(a)实际上是(max{a,-inf})。注意修改的时候和(-inf)取个(max),不然很容易就爆掉了。

  下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define max(a,b) (a>b?a:b)
#define maxn 500010
#define INF (1LL<<60)

using namespace std;
typedef long long llg;

int n,m,L,R;
llg na[maxn<<2],nb[maxn<<2];
llg pa[maxn<<2],pb[maxn<<2],za,zb;

int getint(){
	int w=0;bool q=0;
	char c=getchar();
	while((c>'9'||c<'0')&&c!='-') c=getchar();
	if(c=='-') c=getchar(),q=1;
	while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
	return q?-w:w;
}

void pushdown(int u){
	for(int i=0,v;v=u<<1|i,i<2;i++){
		pa[v]=max(pa[v],pa[u]+na[v]);
		pb[v]=max(pb[v],max(pb[u],nb[v]+pa[u]));
		na[v]=max(na[v]+na[u],-INF);
		nb[v]=max(nb[v]+na[u],nb[u]);
	}
	na[u]=nb[u]=pa[u]=pb[u]=0;
}

void build(int u,int l,int r){
	int lc=u<<1,lv=u<<1|1,mid=(l+r)>>1;
	if(l==r) na[u]=pa[u]=getint();
	else build(lc,l,mid),build(lv,mid+1,r);
}

void add(int u,int l,int r){
	int lc=u<<1,lv=u<<1|1,mid=(l+r)>>1;
	if(L<=l && r<=R){
		na[u]=max(na[u]+za,-INF);
		nb[u]=max(nb[u]+za,zb);
		pa[u]=max(pa[u],na[u]);
		pb[u]=max(pb[u],nb[u]);
		return;
	}
	pushdown(u);
	if(L<=mid) add(lc,l,mid);
	if(R>mid) add(lv,mid+1,r);
}

void query(bool w){
	int u=1,l=1,r=n,mid;
	while(l!=r){
		mid=(l+r)>>1;
		pushdown(u); u<<=1;
		if(L<=mid) r=mid;
		else u|=1,l=mid+1;
	}
	za=w?na[u]:pa[u];
	zb=w?nb[u]:pb[u];
}

int main(){
	File("a");
	n=getint(),m=getint();
	build(1,1,n);
	while(m--){
		int ty=getint(),x;
		if(ty<=3){
			L=getint(),R=getint();x=getint();
			if(ty==1) za=x,zb=0;
			if(ty==2) za=-x,zb=0;
			if(ty==3) za=-INF,zb=x;
			add(1,1,n);
		}
		else{
			L=R=getint(); query(ty==4);
			printf("%lld
",max(za,zb));
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/lcf-2000/p/6579097.html