zoukankan      html  css  js  c++  java
  • BZOJ3064:CPU监控

    浅谈区间最值操作和历史最值问题:https://www.cnblogs.com/AKMer/p/10225100.html

    题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=3064

    我直接用论文写法写的……论文题解如下:

    刚接触这一类问题时,这个例题的难度可能较高,所以我们先忽略区间赋值操作。
    考虑使用传统的懒标记来解决,首先如果只是询问区间最大值,只面要使用区间加减这一个懒标记(用(add)表示)就能解决。
    现在考虑询问区间历史最大值的最大值。我们定义一种新的懒标记:历史最大的加减标记(用(hisadd)表示)。这个标记的定义是:从上一次把这个节点的标记下传的时刻到当前时刻这一时间段中,这个节点中的(add)标记值到达过的最大值。
    现在考虑把第(fa)个节点的标记下传到它的儿子(p),不难发现标记是可以合并的:

    (hisadd_p=max(hisadd_p,add_p+hisadd_{fa}),add_p+=add_{fa})

    至于区间历史最大值信息的更新也与标记的合并类似,只面要将当前的区间最大值加上(hisadd)然后与原来的历史最大值进行比较即可。
    现在回到原题,我们观察在修改操作过程中,被影响到的节点的变化:如果一个节点没有发生标记下传,那么最开始它一直被区间加减操作所影响,这时我们可以用上面描述的(hisadd)标记来记录,直到某一时刻,这个节点被区间覆盖标记影响,那么这时这个节点中的所有数都变得完全相同,再之后的所有区间加减修改,对这个节点来说,与区间覆盖操作并没有不同。
    因此每一个节点受到的标记可以分成两个部分:第一个部分是区间加减,第二个部分是区间覆盖。因此我们可以用 ((hisadd,hiscov))来表示历史最值标记,它的定义是当前区间在第一阶段时最大的加减标记是(hisadd),在第二个阶段时最大的覆盖标记是(hiscov)。显然这个标记是可以进行合并与更新的。
    到此我们就使用最传统的懒标记方法解决了这个问题。

    时间复杂度:(O((n+m)logn))

    空间复杂度:(O(n))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int maxn=1e5+5;
    
    int n,m;
    char s[20];
    int a[maxn];
    
    int read() {
    	int x=0,f=1;char ch=getchar();
    	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    	return x*f;
    }
    
    struct segment_tree {
    	struct tree_node {
    		bool bo1,bo2;
    		int hismx,mx,hiscov,cov,hisadd,add;
    	}tree[maxn<<2];
    
    	void update(int p) {
    		tree[p].mx=max(tree[p<<1].mx,tree[p<<1|1].mx);
    		tree[p].hismx=max(tree[p<<1].hismx,tree[p<<1|1].hismx);
    	}
    
    	void build(int p,int l,int r) {
    		if(l==r) {
    			tree[p].mx=tree[p].hismx=a[l];
    			return;
    		}
    		int mid=(l+r)>>1;
    		build(p<<1,l,mid);
    		build(p<<1|1,mid+1,r);
    		update(p);
    	}
    	
    	void add_tag(int p,int v) {
    		if(tree[p].bo2) {
    			tree[p].cov+=v;
    			tree[p].hiscov=max(tree[p].hiscov,tree[p].cov);
    		}
    		else {
    			tree[p].add+=v;
    			if(!tree[p].bo1)tree[p].hisadd=v,tree[p].bo1=1;
    			else tree[p].hisadd=max(tree[p].hisadd,tree[p].add);
    		}
    		tree[p].mx+=v;
    		tree[p].hismx=max(tree[p].hismx,tree[p].mx);
    	}
    	
    	void cov_tag(int p,int v) {
    		tree[p].cov=tree[p].mx=v;
    		tree[p].hismx=max(tree[p].hismx,v);
    		if(!tree[p].bo2)tree[p].hiscov=v,tree[p].bo2=1;
    		else tree[p].hiscov=max(tree[p].hiscov,v);
    	}
    
    	void solve1(int p,int v,int hisv) {
    		if(tree[p].bo2) {
    			tree[p].hiscov=max(tree[p].hiscov,tree[p].cov+hisv);
    			tree[p].cov+=v;
    			tree[p].hismx=max(tree[p].hismx,tree[p].hiscov);
    		}
    		else {
    			if(!tree[p].bo1)tree[p].bo1=1,tree[p].hisadd=hisv;
    			else tree[p].hisadd=max(tree[p].hisadd,tree[p].add+hisv);
    			tree[p].add+=v;
    			tree[p].hismx=max(tree[p].hismx,tree[p].mx+hisv);
    		}
    		tree[p].mx+=v;
    	}
        
    	void solve2(int p,int v,int hisv) {
    		if(!tree[p].bo2)tree[p].hiscov=hisv,tree[p].bo2=1;
    		else tree[p].hiscov=max(tree[p].hiscov,hisv);
    		tree[p].mx=tree[p].cov=v;
    		tree[p].hismx=max(tree[p].hismx,tree[p].hiscov);
    	}
    
    	void push_down(int p) {
    		if(tree[p].bo1) {
    			solve1(p<<1,tree[p].add,tree[p].hisadd);
    			solve1(p<<1|1,tree[p].add,tree[p].hisadd);
    			tree[p].bo1=0,tree[p].add=0;
    		}
    		if(tree[p].bo2) {
    			solve2(p<<1,tree[p].cov,tree[p].hiscov);
    			solve2(p<<1|1,tree[p].cov,tree[p].hiscov);
    			tree[p].bo2=0;
    		}
    	}
    	
    	void plus(int p,int l,int r,int L,int R,int v) {
    		if(L<=l&&r<=R) {add_tag(p,v);return;}
    		int mid=(l+r)>>1;push_down(p);
    		if(L<=mid)plus(p<<1,l,mid,L,R,v);
    		if(R>mid)plus(p<<1|1,mid+1,r,L,R,v);
    		update(p);
    	}
    
    	void cover(int p,int l,int r,int L,int R,int v) {
    		if(L<=l&&r<=R) {cov_tag(p,v);return;}
    		int mid=(l+r)>>1;push_down(p);
    		if(L<=mid)cover(p<<1,l,mid,L,R,v);
    		if(R>mid)cover(p<<1|1,mid+1,r,L,R,v);
    		update(p);
    	}
    
    	int queryMax(int p,int l,int r,int L,int R,int opt) {
    		if(L<=l&&r<=R) {
    			if(opt)return tree[p].mx;
    			return tree[p].hismx;
    		}
    		int mid=(l+r)>>1,res=-2e9;push_down(p);
    		if(L<=mid)res=queryMax(p<<1,l,mid,L,R,opt);
    		if(R>mid)res=max(res,queryMax(p<<1|1,mid+1,r,L,R,opt));
    		return res;
    	}
    }T;
    
    int main() {
    	n=read();
    	for(int i=1;i<=n;i++)
    		a[i]=read();
    	T.build(1,1,n);m=read();
    	for(int i=1;i<=m;i++) {
    		scanf("%s",s+1);
    		int l=read(),r=read(),v=(s[1]!='Q'&&s[1]!='A'?read():0);
    		if(s[1]=='P')T.plus(1,1,n,l,r,v);
    		if(s[1]=='C')T.cover(1,1,n,l,r,v);
    		if(s[1]=='Q')printf("%d
    ",T.queryMax(1,1,n,l,r,1));
    		if(s[1]=='A')printf("%d
    ",T.queryMax(1,1,n,l,r,0));
    	}
    	return 0;
    }
    
  • 相关阅读:
    go 正则表达式
    go 发送邮件
    beego 定时任务
    go 字符串操作
    BARTScore试试
    《A method for detecting text of arbitrary shapes in natural scenes that improves text spotting》笔记
    CPM-2
    Foxmail配置qq邮箱
    声音克隆MockingBird
    多模态摘要综述
  • 原文地址:https://www.cnblogs.com/AKMer/p/10232304.html
Copyright © 2011-2022 走看看