题目传送门
给定长度为
N
N
N 的数列
A
A
A,然后输入
M
M
M 行操作指令。
第一类指令形如
C
C
C
l
l
l
r
r
r
d
d
d,表示把数列中第
l
∼
r
l∼r
l∼r 个数都加
d
d
d。
第二类指令形如
Q
Q
Q
x
x
x,表示询问数列中第
x
x
x 个数的值。
对于每个询问,输出一个整数表示答案。
第一行包含两个整数
N
N
N 和
M
M
M。
第二行包含
N
N
N 个整数
A
[
i
]
A[i]
A[i]。
接下来
M
M
M 行表示
M
M
M 条指令,每条指令的格式如题目描述所示。
对于每个询问,输出一个整数表示答案。
每个答案占一行。
1
≤
N
,
M
≤
1
0
5
,
1≤N,M≤10^5,
1≤N,M≤105,
∣
d
∣
≤
10000
,
|d|≤10000,
∣d∣≤10000,
∣
A
[
i
]
∣
≤
1
0
9
|A[i]|≤10^9
∣A[i]∣≤109
10 5
1 2 3 4 5 6 7 8 9 10
Q 4
Q 1
Q 2
C 1 6 3
Q 2
4
1
2
5
显然是一道树状数组的板子题
对于每个点,通过树状数组记录它更改的值
用一个类似于差分的思想
将
x
−
n
x-n
x−n抬高一格,再将
y
+
1
−
n
y+1-n
y+1−n降低一格
就等价于将
x
−
y
x-y
x−y抬高一格
单点查询只需要将原数加上它改变过的值即可
#include<bits/stdc++.h> using namespace std; const int N=500010; int n,a[N],c[N],m,maxn=-1; void add(int x,int y) { for(;x<=n;x+=x&-x) c[x]+=y; } int ask(int x) { int ans=0; for(;x;x-=x&-x) ans+=c[x]; return ans; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++) { char x; scanf("%s",&x); if(x=='C') { int y,z,w; scanf("%d%d%d",&y,&z,&w); add(y,w); add(z+1,-w); } else { int y; scanf("%d",&y); printf("%d\n",a[y]+ask(y)); } } return 0; }