POJ 3468 一个复杂的数学问题

题目链接

题目大意:

一个序列,n个数字

两个操作,C x y z 表示 x 到 y 区间内的数字都加 z

Q x y 表示查询 x 到 y 的区间和

线段树模板题,注意数据范围就好了,sum 和 标记都用long long基本就可以了

#include <iostream>
#include <cstdio>
#include <cstring>
#define mem(a, b) memset(a, b, sizeof a)
#pragma warning (disable:4996)
#pragma warning (disable:6031)
#pragma warning (disable:26451)
#pragma warning (disable:4244)
using namespace std;
typedef long long ll;
const int N = 110000;
struct {
	int l, r;
	ll lazy;
	ll sum;
}c[N *  4];
ll n, m;
void build(int l, int r, int k) {
	c[k].l = l;
	c[k].r = r;
	if (l == r) {
		scanf("%lld", &c[k].sum);
		return;
	}
	int mid = (l + r) / 2;
	build(l, mid, k * 2);
	build(mid + 1, r, k * 2 + 1);
	c[k].sum = c[k * 2].sum + c[k * 2 + 1].sum;
}
void down(int k) {
	if (c[k].lazy) {
		c[k * 2].sum += (c[k * 2].r - c[k * 2].l + 1) * c[k].lazy;
		c[k * 2 + 1].sum += (c[k * 2 + 1].r - c[k * 2 + 1].l + 1) * c[k].lazy;
		c[k * 2 + 1].lazy += c[k].lazy;
		c[k * 2].lazy += c[k].lazy;
		c[k].lazy = 0;
	}
}
void update(int l, int r, int k, int d) {
	if (l <= c[k].l && r >= c[k].r) {
		c[k].sum += (c[k].r - c[k].l + 1) * d;
		c[k].lazy += d;
		return;
	}
	down(k);
	int mid = (c[k].l + c[k].r) / 2;
	if (l <= mid)update(l, r, k * 2, d);
	if (r > mid)update(l, r, k * 2 + 1, d);
	c[k].sum = c[k * 2].sum + c[k * 2 + 1].sum;
}
ll query(int l, int r, int k) {
	if (l <= c[k].l && r >= c[k].r) {
		return c[k].sum;
	}
	else if (l > c[k].r || r < c[k].l) {
		return 0;
	}
	down(k);
	return query(l, r, k * 2) + query(l, r, k * 2 + 1);
}
int main()
{
	while (~scanf("%lld %lld", &n, &m)) {
		mem(c, 0);
		build(1, n, 1);
		while (m--) {
			char ch[5];
			scanf("%s", ch);
			if (ch[0] == 'Q') {
				int x, y;
				scanf("%d %d", &x, &y);
				printf("%lld\n", query(x, y, 1));
			}
			else {
				int x, y;
				ll z;
				scanf("%d %d %lld", &x, &y, &z);
				update(x, y, 1, z);
			}
		}
	}
	
	return 0;
}
发布了165 篇原创文章 · 获赞 11 · 访问量 9641

猜你喜欢

转载自blog.csdn.net/weixin_43701790/article/details/104079958