题目链接: 敌兵布阵
解题思路
本题是非常基础的线段树模板考察
线段树的单点修改 + 区间查询, 当然, 树状数组也可以处理本题, 所以给出两种思路供参考.
AC代码(线段树)
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 5E4 + 10;
int w[N];
struct node {
int l, r;
int sum;
}t[N << 2];
void pushup(int x) { t[x].sum = t[x << 1].sum + t[x << 1 | 1].sum; }
void build(int l, int r, int x = 1) {
t[x] = { l, r, w[l] };
if (l == r) return;
int mid = l + r >> 1;
build(l, mid, x << 1), build(mid + 1, r, x << 1 | 1);
pushup(x);
}
void modify(int a, int c, int x = 1) {
if (a == t[x].l && a == t[x].r) { t[x].sum += c; return; }
int mid = t[x].l + t[x].r >> 1;
modify(a, c, x << 1 | (a > mid));
pushup(x);
}
int ask(int l, int r, int x = 1) {
if (l <= t[x].l && r >= t[x].r) return t[x].sum;
int mid = t[x].l + t[x].r >> 1;
int res = 0;
if (l <= mid) res += ask(l, r, x << 1);
if (r > mid) res += ask(l, r, x << 1 | 1);
return res;
}
int main()
{
int tt; cin >> tt;
rep(T, tt) {
printf("Case %d:\n", T);
int n; scanf("%d", &n);
rep(i, n) scanf("%d", &w[i]);
build(1, n);
while (true) {
char s[10]; scanf("%s", s);
if (s[0] == 'E') break;
int a, c; scanf("%d %d", &a, &c);
if (s[0] == 'A') modify(a, c);
else if (s[0] == 'S') modify(a, -c);
else if (s[0] == 'Q') printf("%d\n", ask(a, c));
}
}
return 0;
}
AC代码(树状数组)
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 5E4 + 10;
int t[N];
int n, m;
int lowbit(int x) { return x & -x; }
void add(int x, int c) { for (int i = x; i <= n; i += lowbit(i)) t[i] += c; }
int ask(int x) {
int res = 0;
for (int i = x; i; i -= lowbit(i)) res += t[i];
return res;
}
int main()
{
int tt; cin >> tt;
rep(T, tt) {
printf("Case %d:\n", T);
scanf("%d", &n);
rep(i, n) t[i] = 0; //初始化
rep(i, n) { int x; scanf("%d", &x); add(i, x); }
while (true) {
char s[10]; scanf("%s", s);
if (s[0] == 'E') break;
int a, b; scanf("%d %d", &a, &b);
if (s[0] == 'A') add(a, b);
else if (s[0] == 'S') add(a, -b);
else if (s[0] == 'Q') printf("%d\n", ask(b) - ask(a - 1));
}
}
return 0;
}
个人习惯: 因为树状数组代码相较线段树而言属实短很多, 也不容易出错, 因此还是推荐大家一些简单题目可以考虑采用树状数组进行维护.