【线段树 成段更新 lazy标记】LOJ 1164

KIDx的解题报告

 

题目链接:http://lightoj.com/volume_showproblem.php?problem=1164

 

题意:区间内初始时全部为0

命令1:0 x y v; 从x到y全部+v

命令2:1 x y; 输出x到y的值的总和

典型lazy的应用

#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <queue>
#include <utility>
#include <iomanip>
#include <stack>
#include <list>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <ctype.h>
using namespace std;
#define inf 0x3fffffff
#define M 100005
#define LL long long
#define Max 26

struct Node{
	int l, r;			//sum是l到r的总和
	LL v, sum;			//v积累要加的数,需要往下时才更新儿子:lazy标记
}N[M<<2];

void create (int u, int a, int b)
{
	N[u].l = a, N[u].r = b, N[u].v = N[u].sum = 0;
	if (a == b) return ;
	int mid = (a + b) >> 1, lc = u+u, rc = lc+1;
	create (lc, a, mid);
	create (rc, mid+1, b);
}

void update (int u, int a, int b, LL c)
{
	if (a <= N[u].l && b >= N[u].r)
	{
		N[u].v += c;
		N[u].sum += c * (N[u].r-N[u].l+1);		//注意积累是用+=
		return ;
	}
	int lc = u+u, rc = lc+1;
	if (N[u].v > 0)			//lazy一下,需要访问我儿子,我才去更新
	{
		N[lc].v += N[u].v;
		N[lc].sum += N[u].v * (N[lc].r-N[lc].l+1);
		N[rc].v += N[u].v;
		N[rc].sum += N[u].v * (N[rc].r-N[rc].l+1);
		N[u].v = 0;
	}
	if (a <= N[lc].r)
		update (lc, a, b, c);
	if (b >= N[rc].l)
		update (rc, a, b, c);
	N[u].sum = N[lc].sum + N[rc].sum;
}

LL find (int u, int a, int b) //和比较大,要用long long
{
	if (a <= N[u].l && b >= N[u].r)
		return N[u].sum;
	LL m1 = 0, m2 = 0;
	int lc = u+u, rc = lc+1;
	if (N[u].v > 0)			//同理lazy一下
	{
		N[lc].v += N[u].v;
		N[lc].sum += N[u].v * (N[lc].r-N[lc].l+1);
		N[rc].v += N[u].v;
		N[rc].sum += N[u].v * (N[rc].r-N[rc].l+1);
		N[u].v = 0;
	}
	if (a <= N[lc].r)
		m1 = find (lc, a, b);
	if (b >= N[rc].l)
		m2 = find (rc, a, b);
	return m1+m2;
}

int main()
{
	LL c;
	int t, cc = 1, n, q, k, a, b;
	scanf ("%d", &t);
	while (t--)
	{
		scanf ("%d%d", &n, &q);
		create (1, 1, n);
		printf ("Case %d:\n", cc++);
		while (q--)
		{
			scanf ("%d%d%d", &k, &a, &b);
			a++, b++;
			if (k) printf ("%lld\n", find (1, a, b));
			else scanf ("%lld", &c), update (1, a, b, c);
		}
	}
    return 0;
}

 

你可能感兴趣的:(数据结构,C++,算法,ACM,KIDx)