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

江枫思渺然 提交于 2019-12-19 21:06:46

链接:

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:\n", iCase++);

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

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

    }
    return 0;
}

 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!