区间查改【线段树】

>Link

ybtoj区间查改

luogu P3372


>解题思路

线段树的模板题,加上lazy懒标记优化
我一开始WA了,改了好久,结果发现是数组开小了我服了啊


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000010
#define LL long long
using namespace std;

int n, q;
LL a[N], t[N * 5], lazy[N * 5];

void build (int k, int l, int r)
{
	if (l == r)
	{
		t[k] = a[l];
		return;
	}
	int mid = (l + r) / 2;
	build (k * 2, l, mid);
	build (k * 2 + 1, mid + 1, r);
	t[k] = t[k * 2] + t[k * 2 + 1];
} //这个build可要可不要,可以直接用insert代替
void down (int k, int l, int r)
{
	if (!lazy[k]) return;
	t[k] += lazy[k] * (r - l + 1);
	lazy[k * 2] += lazy[k];
	lazy[k * 2 + 1] += lazy[k];
	lazy[k] = 0;
}
void insert (int k, int l, int r, int ll, int rr, LL p)
{
	down (k, l, r); //下置懒标记放在最前面
	if (ll == l && r == rr)
	{
		lazy[k] += p;
		return;
	}
	t[k] += p * (rr - ll + 1);
	int mid = (l + r) / 2;
	if (ll <= mid)
	  insert (k * 2, l, mid, ll, min (mid, rr), p);
	if (rr > mid)
	  insert (k * 2 + 1, mid + 1, r, max (mid + 1, ll), rr, p);
}
LL ask (int k, int l, int r, int ll, int rr)
{
	down (k, l, r);
	if (ll <= l && r <= rr) return t[k];
	int mid = (l + r) / 2;
	LL sum = 0;
	if (ll <= mid)
	  sum += ask (k * 2, l, mid, ll, rr);
	if (rr > mid)
	  sum += ask (k * 2 + 1, mid + 1, r, ll, rr);
	return sum;
}

int main()
{
	int e, l, r, x;
	scanf ("%d%d", &n, &q);
	for (int i = 1; i <= n; i++) scanf ("%lld", &a[i]);
	build (1, 1, n);
	while (q--)
	{
		scanf ("%d", &e);
		if (e == 1)
		{
			scanf ("%d%d%d", &l, &r, &x);
			insert (1, 1, n, l, r, x);
		}
		else
		{
			scanf ("%d%d", &l, &r);
			printf ("%lld\n", ask (1, 1, n, l, r));
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值