BZOJ 3064 CPU监控

题目链接:CPU监控

  学习一番线段树的历史标记~

  这道题就是区间加法,区间赋值,要询问区间最大值 和 区间历史最大值的最大值。

  然后这种题就是在现有标记的基础上多弄一套标记,维护这个点出现过的最大的标记。然后下传标记的时候注意要先传历史标记再传现在的标记。

  王队告诉我说,关于历史标记,可以理解成每个节点有过很多标记,可以看成每个节点都有一个标记队列。这样的话,现在的标记就是在维护这个队列的最后一个,历史标记就是这个队列的(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 INF (-2147483647)
#define maxn 100010

using namespace std;
typedef long long llg;

int n,m,L,R,_nm,_pm,z,_;
int nmax[maxn<<2],nadd[maxn<<2],ncov[maxn<<2];//现在的标记
int pmax[maxn<<2],padd[maxn<<2],pcov[maxn<<2];//历史标记

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 update(int u){
	nmax[u]=max(nmax[u<<1],nmax[u<<1|1]);
	pmax[u]=max(pmax[u<<1],pmax[u<<1|1]);
}

void pushdown(int u){
	for(int i=0,v;i<2;i++){
		v=u<<1|i;
		pmax[v]=max(pmax[v],nmax[v]+padd[u]);
		pmax[v]=max(pmax[v],pcov[u]);
		if(ncov[v]==INF) padd[v]=max(padd[v],nadd[v]+padd[u]);
		else pcov[v]=max(pcov[v],ncov[v]+padd[u]);
		if(nadd[u]){
			nmax[v]+=nadd[u];
			if(ncov[v]==INF) nadd[v]+=nadd[u];
			else ncov[v]+=nadd[u];
		}
		if(ncov[u]!=INF){
			nmax[v]=ncov[u];
			ncov[v]=ncov[u]; nadd[v]=0;
			pcov[v]=max(pcov[v],pcov[u]);
		}
	}
	padd[u]=nadd[u]=0,pcov[u]=ncov[u]=INF;
}

void build(int u,int l,int r){
	pcov[u]=ncov[u]=INF;
	int lc=u<<1,lv=u<<1|1,mid=(l+r)>>1;
	if(l==r) nmax[u]=pmax[u]=getint();
	else build(lc,l,mid),build(lv,mid+1,r),update(u);
}

void query(int u,int l,int r){
	if(l!=r) pushdown(u);
	if(l>=L && r<=R) _nm=max(_nm,nmax[u]),_pm=max(_pm,pmax[u]);
	else{
		int mid=(l+r)>>1;
		if(L<=mid) query(u<<1,l,mid);
		if(R>mid) query(u<<1|1,mid+1,r);
	}
}

void add(int u,int l,int r){
	if(l!=r) pushdown(u);
	if(l>=L && r<=R)
		if(_) padd[u]=nadd[u]=z,pmax[u]=max(pmax[u],nmax[u]+=z);
		else pcov[u]=ncov[u]=z,pmax[u]=max(pmax[u],nmax[u]=z);
	else{
		int mid=(l+r)>>1;
		if(L<=mid) add(u<<1,l,mid);
		if(R>mid) add(u<<1|1,mid+1,r);
		update(u);
	}
}

int main(){
	File("a");
	n=getint(),build(1,1,n);
	m=getint(); char c;
	while(m--){
		c=getchar();
		while(c!='A' && c!='Q' && c!='P' && c!='C') c=getchar();
		L=getint(); R=getint();
		if(c=='Q' || c=='A'){
			_nm=_pm=INF; query(1,1,n);
			printf("%d
",c=='Q'?_nm:_pm);
		}
		else{
			z=getint(); _=c=='P';
			add(1,1,n);
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/lcf-2000/p/6575689.html