You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

66 lines
2.0 KiB

2 years ago
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
const int N = 1e5 + 10;
int n;
int t[N << 1];
void build() {
for (int i = 0; i < n; i++) t[n + i] = read();
for (int i = n - 1; i; i--) t[i] = t[i << 1] + t[i << 1 | 1];
}
void modify(int l, int r, int value) {
for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
if (l & 1) t[l++] += value;
if (r & 1) t[--r] += value;
}
}
//区间查询
int query(int l, int r) { // sum on interval [l, r)
int res = 0;
for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
//① 如果l是奇数l是父亲的右孩子(看一下上面的图,确实是右孩子)
// (1) 此时,只有它自己有用,它的父亲不包含在查询区间内。自己加上,把略过即可
// (2) 怎么略过呢?巧妙的办法:本轮次不加自己父亲,下软移动到右边的兄弟节点的父亲上去! l= (l+1) >> 1
//② 如果l是偶数那么l就是父亲的左儿子整个区间完整命中直接研究它父亲的sum即可 l>>=1
if (l & 1) res += t[l++];
//与上面代码对称的写法
if (r & 1) res += t[--r];
}
return res;
}
int main() {
//文件输入输出
#ifndef ONLINE_JUDGE
freopen("zkw_Study_2.in", "r", stdin);
#endif
n = read();
build();
modify(0, 1, 1); //修改[0,1)也是就是修改下标0的值为1
for (int i = n; i < 2 * n; i++) printf("%d ", t[i]);
puts("");
printf("%d\n", query(1, 3)); //下标从0开始查询[1,3)=3
return 0;
//感悟这东西区间修改区间查询就OK了没有什么单点修改单点查询直接上区间修改、区间查询不就行了吗
}