(线段树 点更新 区间求和)lightoj1112

链接:

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=88230#problem/D (密码0817)

Description

Robin Hood likes to loot rich people since he helps the poor people with this money. Instead of keeping all the money together he does another trick. He keeps n sacks where he keeps this money. The sacks are numbered from 0 to n-1.

Now each time he can he can do one of the three tasks.

1)                  Give all the money of the ith sack to the poor, leaving the sack empty.

2)                  Add new amount (given in input) in the ith sack.

3)                  Find the total amount of money from ith sack to jth sack.

Since he is not a programmer, he seeks your help.

Input

Input starts with an integer T (≤ 5), denoting the number of test cases.

Each case contains two integers n (1 ≤ n ≤ 105) and q (1 ≤ q ≤ 50000). The next line contains n space separated integers in the range [0, 1000]. The ith integer denotes the initial amount of money in the ith sack (0 ≤ i < n).

Each of the next q lines contains a task in one of the following form:

1 i        Give all the money of the ith(0 ≤ i < n) sack to the poor.

2 i v     Add money v (1 ≤ v ≤ 1000) to the ith(0 ≤ i < n) sack.

3 i j      Find the total amount of money from ith sack to jth sack (0 ≤ i ≤ j < n).

Output

For each test case, print the case number first. If the query type is 1, then print the amount of money given to the poor. If the query type is 3, print the total amount from ith to jth sack.

Sample Input

1

5 6

3 2 1 4 5

1 4

2 3 4

3 0 3

1 2

3 0 4

1 1

Sample Output

Case 1:

5

14

1

13

2

代码:


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;


#define Lson (r<<1)
#define Rson (r<<1|1)
#define Mid e[r].mid()

const int N = 100005;

struct node
{
    int L, R, sum;
    int mid()
    {
        return (L+R)/2;
    }
} e[N<<2];

int a[N], sum;

void BuildTree(int r, int L, int R)
{
    e[r].L = L , e[r].R = R;

    if(L==R)
    {
        e[r].sum = a[L];
        return ;
    }

    BuildTree(Lson, L, Mid);
    BuildTree(Rson, Mid+1, R);

    e[r].sum = e[Lson].sum + e[Rson].sum;
}

void Oper(int r, int i, int w)
{
    if(e[r].L == e[r].R)
    {
        e[r].sum = w;
        return ;
    }
    if(i<=Mid)
    Oper(Lson, i, w);
    else
    Oper(Rson, i, w);

    e[r].sum = e[Lson].sum + e[Rson].sum;
}

int Query(int r, int L, int R)
{
    if(e[r].L==L && e[r].R==R)
      return e[r].sum;

    if(R<=Mid)
        return Query(Lson, L, R);
    else if(L>Mid)
        return Query(Rson, L, R);
    else
    {
        int LL = Query(Lson, L, Mid);
        int RR = Query(Rson, Mid+1, R);

        return LL + RR;
    }

}


int main()
{
    int t, n, m, iCase=1;
    scanf("%d", &t);

    while(t--)
    {
      int i, L, R, w, x;

      scanf("%d%d", &n, &m);

      for(i=1; i<=n; i++)
        scanf("%d", &a[i]);

      BuildTree(1, 1, n);

      printf("Case %d:
", iCase++);

      while(m--)
      {
          scanf("%d", &x);
          if(x==3)
          {
              scanf("%d%d", &L, &R);
              sum = 0;
              L++, R++;
              printf("%d
", Query(1, L, R));
          }
          else
          {
              scanf("%d", &i);
              i++;

              if(x==1)
              {
                  printf("%d
", a[i]);
                  a[i] = 0;
              }
              else
              {
                  scanf("%d", &w);
                  a[i] += w;
              }
              Oper(1, i, a[i]); ///由于都是点的操作,可以直接操做后在去操作树,感觉和直接操作树是一样的,不过对于///这题来说,这种似乎更好些, 因为有加和清零的,对点的操作是不一样的, 然而区间查询就很简单了,不说了
          }
      }

    }
    return 0;
}
勿忘初心
原文地址:https://www.cnblogs.com/YY56/p/4738471.html