思路
区间查询,自然就想到差分。大佬的线段树我看不懂,我就用差分来解决这道题。
我们用
首先如何修改部分数组的每个数值?
我们很容易地发现修改部分数组中,区间中每一个数字和前后数字的差只有第一个和最后一个变了。我们可以先将数组 x x x 设为全部为 0 0 0(全是 0 0 0 的数组相减后自然全部为 0 0 0),每次修改我们将数组进行如下处理:
- x l ← x l + v a l x_l \gets x_l + val xl←xl+val
-
x
r
+
1
←
x
r
+
1
−
v
a
l
x_{r + 1} \gets x_{r + 1} - val
xr+1←xr+1−val
这样就修改了差分数组。
差分数组如何变成原数组?
对于数组中的每一个数字,我们只要从 1 1 1 到 n − 1 n - 1 n−1 把 x i + x i − 1 x_i + x_{i - 1} xi+xi−1,就得到了原数组(前缀和)。
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<map>
using namespace std;
int x[10005];
// 快读
inline int read()
{
int x = 0,f = 1;char ch = getchar();
while (ch < '0' or ch > '9'){if (ch == '-') f = -1;ch = getchar();}
while (ch >= '0' and ch<='9'){x = x * 10 + ch - 48;ch = getchar();}
return x * f;
}
//快写
inline void write(int x) {
if(x < 0) putchar('-'),x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
return;
}
//输出char
void writec(char x) {
putchar(x);
return;
}
int main() {
int t = read();
while(t--) {
int n = read(),u = read();
//初始化查分数组
for(int i = 0;i < n;i++) x[i] = 0;
//修改
while(u--) {
int l = read(),r = read(),val = read();
x[l] += val;
x[r + 1] -= val;
}
//前缀和复原数组
for(int i = 1;i < n;i++) x[i] += x[i - 1];
//输出
int q = read();
while(q--) {
int i = read();
write(x[i]),writec('\n');
}
}
return 0;
}
Update
2022/12/22 完成题解
2022/12/24 修改题解(感谢大佬指导指出,将 x 1 x1 x1 改成 x l x_l xl)