洛谷 #2357. 守墓人

题意

守墓人会有几个操作:
1.将[l,r]这个区间所有的墓碑的风水值增加 k。
2.将主墓碑的风水值增加 k
3.将主墓碑的风水值减少 k
4.统计[l,r]这个区间所有的墓碑的风水值之和
5.求主墓碑的风水值
主墓为1

题解

线段树,把主墓拎出来单独算

调试记录

无~~(是真的啥都没干)~~
#include <cstdio>
#define maxn 200005

using namespace std;

int val[maxn], n, f;

struct node{
	int l, r, key, lazy;
}a[maxn << 2];

void build(int cur, int l, int r){
	a[cur].l = l, a[cur].r = r;
	a[cur].lazy = 0;
	if (l == r){
		a[cur].key = val[l];
		return;
	}
	
	int mid = (l + r) >> 1;
	build(cur << 1, l, mid);
	build(cur << 1 | 1, mid + 1, r);
	a[cur].key = a[cur << 1].key + a[cur << 1 | 1].key;
}

void pushdown(int cur){
	if (!a[cur].lazy) return;
	a[cur << 1].lazy += a[cur].lazy;
	a[cur << 1 | 1].lazy += a[cur].lazy;
	a[cur << 1].key += (a[cur << 1].r - a[cur << 1].l + 1) * a[cur].lazy;
	a[cur << 1 | 1].key += (a[cur << 1 | 1].r - a[cur << 1 | 1].l + 1) * a[cur].lazy;
	a[cur].lazy = 0;
}

void update(int cur, int l, int r, int k){
	if (a[cur].r < l || a[cur].l > r) return;
	if (a[cur].l >= l && a[cur].r <= r){
		a[cur].key += (a[cur].r - a[cur].l + 1) * k;
		a[cur].lazy += k;
		return;
	}
	
	pushdown(cur);
	update(cur << 1, l, r, k);
	update(cur << 1 | 1, l, r, k);
	a[cur].key = a[cur << 1].key + a[cur << 1 | 1].key;
}

int Query(int cur, int l, int r){
	if (a[cur].r < l || a[cur].l > r) return 0;
	if (a[cur].l >= l && a[cur].r <= r) return a[cur].key;
	
	pushdown(cur);
	return Query(cur << 1, l, r) + Query(cur << 1 | 1, l, r);
}

int main(){
	scanf("%d%d", &n, &f);
	
	for (int i = 1; i <= n; i++) scanf("%d", &val[i]);
	build(1, 1, n);
	
	while (f--){
		int opt, l, r, k; scanf("%d", &opt);
		
		if (opt == 1){
			scanf("%d%d%d", &l, &r, &k);
			if (l == 1) val[1] += k, l++;
			if (l > r) continue;
			update(1, l, r, k);
		}
		
		if (opt == 2){
			scanf("%d", &k);
			val[1] += k;
		}
		
		if (opt == 3){
			scanf("%d", &k);
			val[1] -= k;
		}
		
		if (opt == 4){
			scanf("%d%d", &l, &r);
			if (l == 1){
				if (r == 1) printf("%d\n", val[1]);
				else printf("%d\n", Query(1, l + 1, r) + val[1]);
			}
			else printf("%d\n", Query(1, l, r));
		}
		
		if (opt == 5) printf("%d\n", val[1]);
	}
	
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值