树状数组模板 Tree Array

---恢复内容开始---

这几天去浙江省选当垫底(Orz我是蒟蒻),然后顺便复习下树状数组

关于树状数组,其实很好理解,主要就是lowbit()操作的巧妙

树状数组是一种非常优雅的数据结构.当要频繁的对数组元素进行修改,同时又要频繁的查询数组内任一区间元素之和的时候,可以考虑使用树状数组. 
换句话说,树状数组最基本的应用: 
对于一个数组,如果有多次操作,每次的操作有两种:1、修改数组中某一元素的值,2、求和,求数组元素a[1]+a[2]+…a[num]的和。 

——Km的小天地

其实树状数组自己写几个代码就很容易理解了,也可以参见这里(Km的小天地)

 1 // Tree-Array 模板 
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 const int MAX=100000;
 5 int a[MAX+10],c[MAX+10],n,s[MAX+10];
 6 int lowbit(int x) {return x&(-x);}
 7 // 修改:修改第x个元素,把第x个元素改为x+delta
 8 // O(logn)
 9 // 支持单点修改,区间更新复杂度O(nlogn)
10 void modify(int x,int delta) {
11     while(x<=n) {
12         c[x]+=delta;
13         x+=lowbit(x);
14     }
15 } 
16 // 查询:查询[1,x]区间和,若要查询[x,y],则需调用[1,y]-[1,x]
17 // O(logn) 
18 int cal(int x) {
19     int ret=0;
20     while(x!=0) {
21         ret+=c[x];
22         x-=lowbit(x);
23     }
24     return ret;
25 }
26 
27 int main() {
28     scanf("%d",&n);
29     for (int i=1;i<=n;++i) {
30         scanf("%d",&a[i]);
31         sum[i]=sum[i-1]+a[i];
32         c[i]=sum[i]-sum[i-lowbit(i)];
33     }
34     int T;
35     scanf("%d",&T);
36     while(T--) {
37         //在线修改查询
38         //这里的代码自行填写 
39     }
40     return 0;
41 }
View Code

树状数组的应用

HDU 1166 敌兵布阵

纯模板题目,很简单。这里要说一点,我的代码在main部分可能缩进会有点乱,因为HDU经常为多组数据,我是先写好TreeArray再进行添加多数据测试。

 1 # include <iostream>
 2 # include <stdio.h>
 3 # include <string.h>
 4 using namespace std;
 5 int a[50010], c[50010], n, sum[50010]={};
 6 int lowbit(int x) {return x&(-x);}
 7 void mdf(int p, int del) {
 8     while(p<=n) {
 9         c[p]+=del;
10         p+=lowbit(p);
11     }
12 }
13 int ca(int dg) {
14     int r=0;
15     while(dg!=0) {
16         r+=c[dg];
17         dg-=lowbit(dg);
18     }
19     return r;
20 }
21 int main() {int T,ft;
22     scanf("%d", &T);ft=T;
23     while(T--) {
24         printf("Case %d:
",ft-T);
25     scanf("%d", &n);
26     for (int i=1;i<=n;++i) { 
27         scanf("%d", &a[i]);
28         sum[i]=sum[i-1]+a[i];
29         c[i]=sum[i]-sum[i-lowbit(i)];
30     }
31     //for (int i=1;i<=n;++i) printf("%d ", c[i]);
32     while(1) {
33         char st[10]; int ta,tb;
34         scanf("%s", st);
35         //printf("%s %d %d",st,ta,tb);
36         if (strcmp(st,"End")==0) break;
37         scanf("%d %d",&ta,&tb);
38         if (strcmp(st,"Add")==0) {
39             mdf(ta,tb);
40         }
41         else if (strcmp(st,"Sub")==0) {
42             mdf(ta,-1*tb);
43         }
44         else if (strcmp(st,"Query")==0) {
45             if(ta>tb) {int p=ta;ta=tb;tb=p;}
46             printf("%d
",ca(tb)-ca(ta-1));
47         }
48     }}
49     return 0;
50 }
View Code

好吧我暂时就写到这一题树状数组,果然我还是太弱了ORZ各位神犇们

---恢复内容结束---

这篇文章由TonyFang发布。 所有解释权归TonyFang所有。 Mailto: tony-fang@map-le.net
原文地址:https://www.cnblogs.com/TonyNeal/p/treearray.html