题目链接在这里
题目大意:
给出n个点的值,有三种操作:
Query x y代表查询[x, y]之内的值的加和
Add x y代表x点增加y
Sub x y代表x点减小y
思路分析:
裸的线段树,盘它!
代码如下:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int MaxN = 50005;
int ans;
struct Node{
int l, r, w;
}tree[MaxN * 4];
void build(int l, int r, int rt){
tree[rt].l = l;
tree[rt].r = r;
if(l == r){
scanf("%d", &tree[rt].w);
return;
}
int mid = (r + l) >> 1;
build(l, mid, rt << 1);
build(mid + 1, r, rt << 1 | 1);
tree[rt].w = tree[rt << 1].w + tree[rt << 1 | 1].w;
}
void query(int l, int r, int rt, int L, int R){
if(l >= L && r <= R){
ans += tree[rt].w;
//printf("???:%d\n", tree[rt].w);
return;
}
int mid = (r + l) >> 1;
if(R <= mid){
query(l, mid, rt << 1, L, R);
}
else if(L > mid){
query(mid + 1, r, rt << 1 | 1, L, R);
}
else{
query(l, mid, rt << 1, L, R);
query(mid + 1, r, rt << 1 | 1, L, R);
}
}
void update(int l, int r, int rt, int pos, int add){
if(l == r){
tree[rt].w += add;
return;
}
int mid = (l + r) >> 1;
if(pos <= mid){
update(l, mid, rt << 1, pos, add);
}
else{
update(mid + 1, r, rt << 1 | 1, pos, add);
}
tree[rt].w = tree[rt << 1].w + tree[rt << 1 | 1].w;
}
int main(){
int t, n, Case = 0;
char str[10];
int x, y;
scanf("%d", &t);
while(t--){
scanf("%d", &n);
build(1, n, 1);
printf("Case %d:\n", ++Case);
while(scanf("%s", str)){
if(str[0] == 'E') break;
scanf("%d %d", &x, &y);
if(str[0] == 'Q'){
ans = 0;
query(1, n, 1, x, y);
printf("%d\n", ans);
}
if(str[0] == 'A'){
update(1, n, 1, x, y);
}
if(str[0] == 'S'){
update(1, n, 1, x, -y);
}
}
}
return 0;
}