BZOJ3064: Tyvj 1518 CPU监控

题目链接http://www.lydsy.com/JudgeOnline/problem.php?id=3064

题目要求很简单,就是维护一个区间最大值和只保留节点最大值的区间最大值。比较麻烦的是带区间修改,普通的lazy_tag会使得第二项被漏算。所以我们需要修改一下lazy_tag,也就是维护一个add,add最大值,set,set最大值,lazy_set,lazy_add,具体的下放自己YY一下就可以写出来了。但真的很恶心,写了两遍才写过。。。

怎么感觉好像没什么好说的了。。。直接上代码吧:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

typedef long long LL;

const int maxn = 100000+10;

int n,q;

int A[maxn];

LL M[maxn*4],Mu[maxn*4],set[maxn*4],add[maxn*4],set_M[maxn*4],add_M[maxn*4];

bool lazy1[maxn*4],lazy2[maxn*4];

void Update(int u) {
	int lc = u<<1,rc = lc|1;
	M[u] = max(M[lc],M[rc]);
	Mu[u] = max(Mu[lc],Mu[rc]);
}

void Build(int u,int l,int r) {
	if(l == r) {M[u] = Mu[u] = A[l];return;}
	int mid = (l+r) >> 1;
	Build(u<<1,l,mid);
	Build(u<<1|1,mid+1,r);
	Update(u);
}

void Make1(int u,LL w) {
	if(lazy1[u]) {
		set[u] += w;
		set_M[u] = max(set[u],set_M[u]);
		Mu[u] = max(Mu[u],set_M[u]);
	}
	else {
		add[u] += w;
		if(!lazy2[u])add_M[u] = w;
		else add_M[u] = max(add_M[u],add[u]);
		lazy2[u] = true;
		Mu[u] = max(Mu[u],M[u]+w);
	}
	M[u] += w;
}

void Make1(int u,LL w,LL MM) {
	if(lazy1[u]) {
		set_M[u] = max(set_M[u],set[u]+MM);
		set[u] += w;
		Mu[u] = max(Mu[u],set_M[u]);
	}
	else {
		if(lazy2[u])add_M[u] = max(add_M[u],add[u]+MM);
		else add_M[u] = MM;
		add[u] += w;
		lazy2[u] = true;
		Mu[u] = max(Mu[u],M[u]+MM);
	}
	M[u] += w;
}

void Make2(int u,LL w) {
	if(lazy1[u]) {
		set[u] = w;set_M[u] = max(set_M[u],set[u]);
	}
	else {
		lazy1[u] = true;set[u] = set_M[u] = w;
	}
	M[u] = w;Mu[u] = max(Mu[u],w);
}

void Make2(int u,LL w,LL MM) {
	if(lazy1[u])set_M[u] = max(set_M[u],MM);
	else set_M[u] = MM;
	set[u] = w;lazy1[u] = true;
	Mu[u] = max(Mu[u],set_M[u]);
	M[u] = w;
}

void pushdown(int u) {
	int lc = u<<1,rc = lc|1;
	if(lazy2[u]) {Make1(lc,add[u],add_M[u]);Make1(rc,add[u],add_M[u]);}
	if(lazy1[u]) {Make2(lc,set[u],set_M[u]);Make2(rc,set[u],set_M[u]);}
	lazy1[u] = lazy2[u] = set[u] = set_M[u] = add[u] = add_M[u] = 0;
}

void Add(int u,int l,int r,int L,int R,int w) {
	if(l >= L && r <= R) {Make1(u,w);return;}
	pushdown(u);
	int mid = (l+r) >> 1;
	if(L <= mid)Add(u<<1,l,mid,L,R,w);
	if(R > mid)Add(u<<1|1,mid+1,r,L,R,w);
	Update(u);
}

void Set(int u,int l,int r,int L,int R,int w) {
	if(l >= L && r <= R) {Make2(u,w);return;}
	pushdown(u);
	int mid = (l+r) >> 1;
	if(L <= mid)Set(u<<1,l,mid,L,R,w);
	if(R > mid)Set(u<<1|1,mid+1,r,L,R,w);
	Update(u);
}

LL query1(int u,int l,int r,int L,int R) {
	if(l >= L && r <= R)return M[u];
	pushdown(u);
	int mid = (l+r) >> 1;
	if(R <= mid)return query1(u<<1,l,mid,L,R);
	if(L > mid)return query1(u<<1|1,mid+1,r,L,R);
	return max(query1(u<<1,l,mid,L,R),query1(u<<1|1,mid+1,r,L,R));
}

LL query2(int u,int l,int r,int L,int R) {
	if(l >= L && r <= R)return Mu[u];
	pushdown(u);
	int mid = (l+r) >> 1;
	if(R <= mid)return query2(u<<1,l,mid,L,R);
	if(L > mid)return query2(u<<1|1,mid+1,r,L,R);
	return max(query2(u<<1,l,mid,L,R),query2(u<<1|1,mid+1,r,L,R));
}

char s[5];

int main() {
	scanf("%d",&n);int a,b,c;
	for(int i = 1; i <= n; i++) {
		scanf("%d",&A[i]);
	}
	Build(1,1,n);
	scanf("%d",&q);
	for(int i = 1; i <= q; i++) {
		scanf("%s",s);
		if(s[0] == 'Q') {
			scanf("%d%d",&a,&b);
			printf("%lld\n",query1(1,1,n,a,b));
		}
		else if(s[0] == 'A') {
			scanf("%d%d",&a,&b);
			printf("%lld\n",query2(1,1,n,a,b));
		}
		else if(s[0] == 'P') {
			scanf("%d%d%d",&a,&b,&c);Add(1,1,n,a,b,c);
		}
		else if(s[0] == 'C') {
			scanf("%d%d%d",&a,&b,&c);Set(1,1,n,a,b,c);
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值