题目描述
Lily 特别喜欢养花,但是由于她的花特别多,所以照料这些花就变得不太容易。她把她的花依次排成一行,每盆花都有一个美观值。如果Lily把某盆花照料的好的话,这盆花的美观值就会上升,如果照料的不好的话,这盆花的美观值就会下降。有时,Lily想知道某段连续的花的美观值之和是多少,但是,Lily的算术不是很好,你能快速地告诉她结果吗?
输入格式
第一行一个整数T,表示有T组测试数据。
每组测试数据的第一行为一个正整数N(N<=50000),表示Lily有N盆花。接下来有N个正整数,第i个正整数ai表示第i盆花的初始美观值(1<=ai<=50)。
接下来每行有一条命令,命令有4种形式:
(1)Add i j, i和j为正整数,表示第i盆花被照料的好,美观值增加j(j<=30)
(2)Sub i j, i和j为正整数,表示第i盆花被照料的不好,美观值减少j(j<=30)
(3)Query i j, i和j为正整数,i<=j,表示询问第i盆花到第j盆花的美观值之和
(4)End,表示结束,这条命令在每组数据最后出现
每组数据的命令不超过40000条
输出格式
对于第i组数据,首先输出"Case i:"和回车。对于每个"Query i j"命令,输出第i盆花到第j盆花的美观值之和。
输入输出样例
输入
1 9
7 9 8 4 4 5 4 2 7
Query 7 9
Add 4 9
Query 3 6
Sub 9 6
Sub 3 3
Query 1 9
End
输出
Case 1:
13
30
50
题目链接
分析:
这道题需要注意的地方:
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#define MAX 50010
using namespace std;
typedef long long LL;
int read(){
int x, f = 1;
char ch;
while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
x = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
return x * f;
}
int tree[4 * MAX]; // 线段树
int lz[4 * MAX]; // 延迟标记
char a[8];
void build(int node, int l, int r){ // 创建线段树
if(l == r){
tree[node] = read();
return;
}
int mid = (l + r) / 2;
build(node * 2, l, mid);
build(node * 2 + 1, mid + 1, r);
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
void update(int n, int index, int l, int r, int node){ // 单点更新,n为更新值,index为更新点,lr为更新范围
if(l == r){
tree[node] += n; // 更新方式,可以自由改动
return;
}
int mid = (l + r) / 2;
// push_down(node,mid-l+1,r-mid); 若既有点更新又有区间更新,需要这句话
if(index <= mid){
update(n, index, l, mid, node * 2);
}else{
update(n, index, mid + 1, r, node * 2 + 1);
}
tree[node] = tree[node * 2] + tree[node * 2 + 1];
}
void push_down(int node, int l, int r){
if(lz[node]){
int mid = (l + r) / 2;
lz[node * 2] += lz[node];
lz[node * 2 + 1] += lz[node];
tree[node * 2] += 1LL * (mid - l + 1) * lz[node];
tree[node * 2 + 1] += 1LL * (r - mid) * lz[node];
lz[node] = 0;
}
}
LL query_range(int node, int L, int R, int l, int r){ // 区间查找
if(l <= L && r >= R) return tree[node];
push_down(node, L, R);
int mid = (L + R) / 2;
LL sum = 0;
if(mid >= l) sum += query_range(node * 2, L, mid, l, r);
if(mid < r) sum += query_range(node * 2 + 1, mid + 1, R, l, r);
return sum;
}
int main(){
int n, i, p, q, t, u;
t = read();
for(i = 1; i <= t; i++){
memset(tree, 0, sizeof(tree));
memset(lz, 0, sizeof(lz));
u = read();
build(1, 1, u);
printf("Case %d:\n", i);
while(scanf("%s", a)){
if(a[0] == 'E') break;
p = read();
q = read();
if(a[0] == 'Q') printf("%lld\n", query_range(1, 1, u, p, q));
else if(a[0] == 'A') update(q, p, 1, u, 1);
else update(-q, p, 1, u, 1);
}
}
return 0;
}