C - A Simple Problem with Integers (线段树lazy区间增减)

You have N integers, A1, A2, … , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, … , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
“C a b c” means adding c to each of Aa, Aa+1, … , Ab. -10000 ≤ c ≤ 10000.
“Q a b” means querying the sum of Aa, Aa+1, … , Ab.
Output

You need to answer all Q commands in order. One answer in a line.
Sample Input

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

Sample Output

4
55
9
15

Hint
The sums may exceed the range of 32-bit integers.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
long long int sum[400002];
long long int add[400002];
void PushUp(int node)
{
  sum[node] = sum[node*2] + sum[node * 2 + 1];
}
//add数组标记
void PushDown(int node, int m)
{
   if(add[node])
   {
     add[node*2] += add[node];
     add[node*2+1] += add[node];
     sum[node*2] += add[node] *(m - (m / 2));
     sum[node*2+1] += add[node] *(m / 2);
     add[node] = 0;
   }
}
void Build(int l, int r, int node)
{
   add[node] = 0;
  if(l==r)
  {
    scanf("%lld", &sum[node]);
    return ;
  }
  int m = (l + r) / 2;
  Build(l, m , node * 2);
  Build(m+1, r, node * 2 + 1);
  PushUp(node);
}
void UpData(int L, int R, int Add, int l, int r, int node)
{
  if(L<=l&&r<=R)
  {
    add[node] += Add;
    sum[node] += (long long int)Add * (r - l + 1);
    return ;
  }
  PushDown(node, r - l + 1);
  int m = (l + r) / 2;
  if(L<=m)
  UpData(L, R, Add, l, m, node * 2);
  if(m<R)
  UpData(L, R, Add, m+1, r, node * 2 + 1);
  PushUp(node);
}
long long int Query(int L, int R, int l, int r, int node)
{
   if(L<=l&&r<=R)
   {
     return sum[node];
   }
   /*^^^^^^^^^^^^^^*/
   PushDown(node, r - l + 1);
   /*^^^^^^^^^^^^^^*/
   long long int ans = 0;
   int m = (l + r) / 2;
   if(L<=m)
   ans += Query(L, R, l, m, node * 2);
   if(R>m)
   ans += Query(L, R, m+1, r, node * 2 + 1);
   return ans;
}
int main()
{
  int n, m, a, b, c;
  char op;
  scanf("%d %d", &n, &m);
  Build(1, n, 1);
  getchar();
  while(m--)
  {
    scanf("%c", &op);
    if(op=='Q')
    {
      scanf("%d %d", &a, &b);
      printf("%lld\n", Query(a, b, 1, n, 1));
    }
    else  if(op=='C')
    {
     scanf("%d %d %d", &a, &b, &c);
     UpData(a, b, c, 1, n, 1);
    }
    getchar();
  }
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值