传送门:题目
题意:
n个营地,告诉你初始时每个营地的人数,之后的操作有三种:
- 某个营地增加人数
- 某个营地减少人数
- 查询营地[i,j]的人数总和。
题解:
典型的线段树单点更新,区间查询。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 50010;
int sum[maxn << 2];
int a[maxn];
void BuildTree(int l, int r, int rt) {
if (l == r) {
sum[rt] = a[l];
return ;
}
int m = (l + r) >> 1;
BuildTree(l, m, rt << 1);
BuildTree(m + 1, r, rt << 1 | 1);
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
int Query(int L, int R, int l, int r, int rt) {//区间查询
if (l >= L && r <= R)
return sum[rt];
int m = (l + r) >> 1;
int ans = 0;
if (L <= m)
ans += Query(L, R, l, m, rt << 1);
if (R > m)
ans += Query(L, R, m + 1, r, rt << 1 | 1);
return ans;
}
void Update(int point, int value, int l, int r, int rt) {//单点更新
if (l == r) {
sum[rt] += value;
return;
}
int m = (l + r) >> 1;
if (point <= m)
Update(point, value, l, m, rt << 1);
else
Update(point, value, m + 1, r, rt << 1 | 1);
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void init() {
memset(sum, 0, sizeof sum);
memset(a, 0, sizeof a);
}
int main(void) {
ios::sync_with_stdio(false);
int T, n, t1, t2, kase = 0;
string str;
cin >> T;
while (T--) {
init();
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
BuildTree(1, n, 1);
kase++;
cout << "Case " << kase << ":" << endl;
while (true) {
cin >> str;
if (str == "End")
break;
cin >> t1 >> t2;
if (str == "Query")
cout << Query(t1, t2, 1, n, 1) << endl;
else if (str == "Add")
Update(t1, t2, 1, n, 1);
else
Update(t1, -t2, 1, n, 1);
}
}
return 0;
}