BZOJ 3064 Tyvj 1518 CPU监控

题解:历史最值线段树

参见吉司机的论文

还是不熟,自己打打不出来

维护当前和历史两套标记,最大值,加法标记,减法标记

每到一个节点先pushdown(不知道为什么)

正确性不是很理解QWQ

还是自己太弱了

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100009;
typedef long long Lint;
const Lint inf=1000000000000000;

int n,m;
Lint a[maxn];

struct SegmentTree{
	int l,r;
	Lint mx[2],tag[2],st[2];
}tree[maxn<<3];

void pushup(int now){
	tree[now].mx[0]=max(tree[now<<1].mx[0],tree[now<<1|1].mx[0]);
	tree[now].mx[1]=max(tree[now<<1].mx[1],tree[now<<1|1].mx[1]);
}
void pushdown(int now){
	int son;
	for(int i=0;i<=1;++i){
		son=now<<1|i;
		tree[son].mx[0]=max(tree[son].mx[0],max(tree[now].st[0],tree[son].mx[1]+tree[now].tag[0]));
		if(tree[son].st[1]==-inf){
			tree[son].tag[0]=max(tree[son].tag[0],tree[son].tag[1]+tree[now].tag[0]);
		}else{
			tree[son].st[0]=max(tree[son].st[0],tree[son].st[1]+tree[now].tag[0]);
		}
		if(tree[now].tag[1]){
			if(tree[son].st[1]!=-inf)tree[son].st[1]+=tree[now].tag[1];
			else tree[son].tag[1]+=tree[now].tag[1];
			tree[son].mx[1]+=tree[now].tag[1];
		}
		if(tree[now].st[1]!=-inf){
			tree[son].st[1]=tree[son].mx[1]=tree[now].st[1];
			tree[son].tag[1]=0;
		}
		tree[son].st[0]=max(tree[son].st[0],max(tree[son].st[1],tree[now].st[0]));
		tree[son].tag[0]=max(tree[son].tag[0],tree[son].tag[1]);
	}
	tree[now].tag[0]=tree[now].tag[1]=0;
	tree[now].st[0]=tree[now].st[1]=-inf;
}

void BuildTree(int now,int l,int r){
	tree[now].l=l;tree[now].r=r;
	tree[now].tag[0]=tree[now].tag[1]=0;
	tree[now].st[0]=tree[now].st[1]=-inf;
	if(l==r){
		tree[now].mx[0]=tree[now].mx[1]=a[l];
		return;
	}
	int mid=(l+r)>>1;
	BuildTree(now<<1,l,mid);
	BuildTree(now<<1|1,mid+1,r);
	pushup(now);
}

void Updatasec(int now,int ll,int rr,Lint x,int opty){
	if(tree[now].l!=tree[now].r)pushdown(now);
	if(tree[now].l>=ll&&tree[now].r<=rr){
		if(opty==0){
			tree[now].mx[1]+=x;tree[now].tag[1]+=x;tree[now].tag[0]=x;
		}else{
			tree[now].st[1]=tree[now].st[0]=tree[now].mx[1]=x;
		}
		tree[now].mx[0]=max(tree[now].mx[0],tree[now].mx[1]);
		return;
	}
	int mid=(tree[now].l+tree[now].r)>>1;
	if(ll<=mid)Updatasec(now<<1,ll,rr,x,opty);
	if(rr>mid)Updatasec(now<<1|1,ll,rr,x,opty);
	pushup(now);
}

Lint Querymax(int now,int ll,int rr,int opty){
	if(tree[now].l!=tree[now].r)pushdown(now);
	if(tree[now].l>=ll&&tree[now].r<=rr){
		return tree[now].mx[opty];
	}
	Lint ans=-inf;
	int mid=(tree[now].l+tree[now].r)>>1;
	if(ll<=mid)ans=max(ans,Querymax(now<<1,ll,rr,opty));
	if(rr>mid)ans=max(ans,Querymax(now<<1|1,ll,rr,opty));
	return ans;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%lld",&a[i]);
	BuildTree(1,1,n);
	scanf("%d",&m);
	while(m--){
		char opty=getchar();
		while(opty<'A'||opty>'Z')opty=getchar();
		int l,r,x;
		scanf("%d%d",&l,&r);
		if(opty=='Q')printf("%lld\n",Querymax(1,l,r,1));
		if(opty=='A')printf("%lld\n",Querymax(1,l,r,0));
		if(opty=='P'){
			scanf("%d",&x);Updatasec(1,l,r,x,0);
		}
		if(opty=='C'){
			scanf("%d",&x);Updatasec(1,l,r,x,1);
		}
	}
	return 0;
}

  

posted @ 2018-02-21 11:36  ws_zzy  阅读(237)  评论(0编辑  收藏  举报