zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    hdu 5007 水题 (2014西安网赛A题)
    hdu 1698 线段树(成段替换 区间求和)
    poj 3468 线段树 成段增减 区间求和
    hdu 2795 公告板 (单点最值)
    UVaLive 6833 Miscalculation (表达式计算)
    UVaLive 6832 Bit String Reordering (模拟)
    CodeForces 124C Prime Permutation (数论+贪心)
    SPOJ BALNUM (数位DP)
    CodeForces 628D Magic Numbers (数位DP)
    POJ 3252 Round Numbers (数位DP)
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/6575689.html
Copyright © 2011-2022 走看看