https://www.acwing.com/problem/content/244/
时/空限制:1s / 64MB
给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:
1、“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。
2、“Q l r”,表示询问 数列中第 l~r 个数的和。
对于每个询问,输出一个整数表示答案。
输入格式
第一行两个整数N,M。
第二行N个整数A[i]。
接下来M行表示M条指令,每条指令的格式如题目描述所示。
输出格式
对于每个询问,输出一个整数表示答案。
每个答案占一行。
数据范围
1≤N,M≤1051≤N,M≤105,
|d|≤10000|d|≤10000,
|A[i]|≤1000000000|A[i]|≤1000000000
输入样例:
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
输出样例:
4
55
9
15
懒标记:当前节点所有子节点需要维护的信息。
#include<iostream>
#define ll long long
using namespace std;
const int N = 100000 + 10;
struct node{
int l, r;
ll sum, add;
}tr[N*4];
ll a[N];
int n,m;
void pushup(node &u, node &l, node &r)
{
u.sum = l.sum + r.sum;
}
void pushup(int u)
{
pushup(tr[u], tr[u<<1], tr[u<<1|1]);
}
void pushdown(int u)//使用懒标计更新子节点
{
auto &root = tr[u], &l = tr[u<<1], &r = tr[u<<1|1];
if(root.add)
{
l.add += root.add;
l.sum += (l.r - l.l + 1) * root.add;
r.add += root.add;
r.sum += (r.r - r.l + 1) * root.add;
root.add = 0;
}
}
void build(int u, int l, int r)
{
if(l == r) tr[u] = {l, r, a[l],0};
else
{
tr[u] = {l,r};
int mid = (l + r) >> 1;
build(u<<1, l, mid);
build(u<<1|1, mid+1, r);
pushup(u);
}
}
ll query(int u, int l, int r)
{
if(tr[u].l >= l && tr[u].r <= r) return tr[u].sum;
pushdown(u);
int mid = (tr[u].l + tr[u].r) >> 1;
ll sum = 0;
if(l <= mid) sum += query(u<<1, l, r);
if(r > mid) sum += query(u<<1|1, l, r);
return sum;
}
void modify(int u, int l, int r, int v)
{
if(tr[u].l >= l && tr[u].r <= r)
{
tr[u].sum += (tr[u].r - tr[u].l + 1) * v;
tr[u].add += v;//此时懒标计未被使用
}
else
{
pushdown(u);
int mid = (tr[u].l + tr[u].r) >> 1;
if(l <= mid) modify(u<<1, l, r, v);
if(r > mid) modify(u<<1|1, l, r, v);
pushup(u);
}
}
int main()
{
cin>>n>>m;
for(int i=1; i<=n; i++)
scanf("%lld",&a[i]);
build(1, 1, n);
char c;
while(m--)
{
getchar();
cin>>c;
if(c == 'Q')
{
int l,r;
cin>>l>>r;
cout<<query(1, l, r)<<endl;
}
else
{
int l, r;
ll val;
cin>>l>>r>>val;
modify(1, l, r, val);
}
}
return 0;
}
// 10 5
// 11 15 -12 -16 18 -8 -4 -9 16 18
// Q 7 8
// C 5 10 -4
// Q 6 6
// C 3 4 2
// Q 1 4