学习笔记-树状数组（三）

由差分到前缀和

简单尝试推导

a1+a2+a3+...+ai

=(c1)+(c1+c2)+(c1+c2+c3)+...+(c1+c2+...+ci)

=c1*(i)+c2*(i-1)+c3*(i-2)+...+ci-1*2+ci*1

...然而貌似还是很不方便

进一步推导

a1+a2+...+ai

=(i+1)*(c1+c2+...+ci)-(c1*1+c2*2+...+ci*i)     ——如果你不想写线段树，请牢记这个推导式

程序实现

区间修改

1 void add(int x,int k,bool f)
2 {
3     while(x<=n)
4     {
5         tree[f][x]+=k;
6         x+=lowbit(x);
7     }
8 }

1 void update(int x, int k)
2 {
5 }

update(x, k);
update(y+1, -k);


区间查询

1 int sch(int x, bool f){
2     int ans = 0;
3     while(x >= 1){
4         ans += tree[f][x];
5         x -= lowbit(x);
6     }
7     return ans;
8 }

1 int sum(int x)
2 {
3     int ans = (x + 1) * (sch(x, 0)) - sch(x, 1);
4     return ans;
5 }

res = sum(y) - sum(x - 1);


例题

LGOJ-P3372

程序实现

 1 #include<cstdio>
2 #include<cctype>
3 #define ll long long
4 using namespace std;
5 ll n, m, tree[2][100010];
7     char ch = getchar();
8     ll f = 1, x = 0;
9     while(!isdigit(ch)){
10         if(ch == '-') f = -1;
11         ch = getchar();
12     }
13     while(isdigit(ch)){
14         x *= 10;
15         x += (ch & 15);
16         ch = getchar();
17     }
18     return f * x;
19 }
20 ll lowbit(ll x){
21     return x & (-x);
22 }
23 void add(ll x,ll k,ll f)
24 {
25     while(x<=n)
26     {
27         tree[f][x]+=k;
28         x+=lowbit(x);
29     }
30 }
31 void update(ll x, ll k)
32 {
35 }
36 ll sch(ll x, ll f){
37     ll ans = 0;
38     while(x >= 1){
39         ans += tree[f][x];
40         x -= lowbit(x);
41     }
42     return ans;
43 }
44 ll sum(int x)
45 {
46     ll ans = (x + 1) * (sch(x, 0)) - sch(x, 1);
47     return ans;
48 }
49 int main(){
51     for(ll i = 1, a = 0, b = 0; i <= n; i++){
53         update(i, b - a);
54         a = b;
55     }
56     while(m--){
58             ll x, y, z;
60             update(x, z); update(y + 1, -z);
61         }
62         else{
63             ll x, y;
69 }