敌兵布阵(线段树+单点更新)


       这道题算是线段树的入门题了,线段树理解的话其实是挺好理解的,但写的话就感觉挺不好写的,毕竟有好几十行代码,讲解的话看下别人的博客,他们讲的我觉得很清楚了,然后如果觉得我的代码风格跟你差不多的,能接受我的这种写法的话,有什么不懂得可以问我。


AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#define lson l, mid, o << 1
#define rson mid + 1, r, o << 1 | 1
#define maxn 50005
using namespace std;
int sum[maxn << 2];
int T,n;
string str;

void Pushup(int o){
  sum[o] = sum[o << 1] + sum[o << 1 | 1];    // 向上更新维护一个sum值
}

void Build(int l, int r, int o){
  if(l == r){
    scanf("%d",&sum[o]);
    return ;
  }
  int mid = (l + r) >> 1;
  Build(lson);
  Build(rson);
  Pushup(o);
}

void Update(int x, int ans, int l, int r,int o){
  if(l == r){
    sum[o] += ans;
    return ;
  }
  int mid = (l + r) >> 1;
  if(x <= mid) Update(x, ans, lson);
  else Update(x, ans, rson);
  Pushup(o);
}

int Query(int L, int R, int l, int r, int o){
  if(L <= l && r <= R){
    return sum[o];
  }
  int mid = (l + r) >> 1;
  int ans = 0;
  if(L <= mid) ans += Query(L, R, lson);
  if(R > mid) ans += Query(L, R, rson);
  return ans;
}


int main()
{
  int Case = 1;
  scanf("%d",&T);
  while(T--){
    scanf("%d",&n);
    Build(1,n,1);
    int a,b;
    printf("Case %d:\n",Case++);
    while(cin>>str){
      if(str == "End")break;
      scanf("%d%d",&a,&b);
      if(str == "Add"){
        Update(a,b,1,n,1);
      }
      else if(str == "Sub"){
        Update(a,-b,1,n,1);
      }
      else{
        printf("%d\n",Query(a,b,1,n,1));
      }
    }
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/charles_zaqdt/article/details/80505201