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;
}