树状数组的基本用法(板子)
写这篇博客,为了方便自己后续复制粘贴板子;
HDU 1166
题意:单点更新,区间查询
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 using namespace std; 5 6 #define lowbit(x) ((x)&-(x)) 7 typedef long long ll; 8 const int maxn=5e5+5; 9 int n, q, a[maxn], c[maxn]; 10 11 void add(int x, int val) 12 { 13 while(x<=n) 14 { 15 c[x]+=val; 16 x+=lowbit(x); 17 } 18 } 19 20 int ask(int x) 21 { 22 int ans=0; 23 while(x>0) 24 { 25 ans+=c[x]; 26 x-=lowbit(x); 27 } 28 return ans; 29 } 30 31 int main() 32 { 33 //freopen("in.txt", "r", stdin); 34 //ios::sync_with_stdio(false); 35 int T, kase=0; cin>>T; 36 while(T--) 37 { 38 cin>>n; 39 memset(c, 0, sizeof(c)); 40 for(int i=1; i<=n; i++) 41 { 42 int x; cin>>x; 43 add(i, x); 44 } 45 46 printf("Case %d:\n", ++kase); 47 char s[10]; 48 while(scanf("%s", s+1), s[1]!='E') 49 { 50 int x,y; cin>>x>>y; 51 if(s[1]=='Q') 52 printf("%d\n", ask(y)-ask(x-1)); 53 else if(s[1]=='A') 54 add(x, y); 55 else 56 add(x, -y); 57 } 58 } 59 return 0; 60 }
HDU 1754
题意:区间查询(最大值),单点更新;
不过好像树状数组在维护最大值好像没有线段树快,这个看看就行了,遇到了还是写线段树吧!
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 using namespace std; 5 6 #define lowbit(x) ((x)&-(x)) 7 typedef long long ll; 8 const int maxn=5e5+5; 9 int n, q, a[maxn], c[maxn]; 10 11 void add(int x, int val) 12 { 13 while(x<=n) 14 { 15 c[x]=val; 16 for(int i=1; i<lowbit(x); i<<=1) 17 c[x]=max(c[x], c[x-i]); 18 x+=lowbit(x); 19 } 20 } 21 22 int ask(int l, int r) 23 { 24 int ans=0; 25 while(l<=r) 26 { 27 ans=max(ans, a[r]); ///注意这一行是和a数组比的 28 r--; 29 for( ; r-l>=lowbit(r); r-=lowbit(r)) 30 ans=max(ans, c[r]); 31 } 32 return ans; 33 } 34 35 int main() 36 { 37 //freopen("in.txt", "r", stdin); 38 ios::sync_with_stdio(false); 39 while(cin>>n>>q) 40 { 41 for(int i=1; i<=n; i++) 42 { 43 cin>>a[i]; 44 add(i, a[i]); 45 } 46 47 while(q--) 48 { 49 char cmd; int x, y; 50 cin>>cmd>>x>>y; 51 if(cmd=='Q') 52 printf("%d\n", ask(x,y)); 53 else 54 { 55 a[x]=y; 56 add(x, y); 57 } 58 } 59 } 60 return 0; 61 }
POJ 3468
题意:区间查询,区间更新;
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 using namespace std; 5 6 #define lowbit(x) ((x)&-(x)) 7 #define _rep(x,y) for(int i=(x); i<=(y); i++) 8 typedef long long ll; 9 const int maxn=1e5+5; 10 ll sum1[maxn], sum2[maxn], sum[maxn]; 11 int n, q, a[maxn], c[maxn]; 12 13 void add(int x, int val) 14 { 15 int i=x; 16 while(i<=n) 17 { 18 sum1[i]+=val; 19 sum2[i]+=val*x; 20 i+=lowbit(i); 21 } 22 } 23 24 void range_add(int l, int r, int x) 25 { 26 add(l, x); add(r+1, -x); 27 } 28 29 ll ask(int x) 30 { 31 ll ans=0; int i=x; 32 while(i>0) 33 { 34 ans+=(x+1)*sum1[i]-sum2[i]; 35 i-=lowbit(i); 36 } 37 return ans; 38 } 39 40 ll range_ask(int l, int r) 41 { 42 return ask(r)-ask(l-1); 43 } 44 45 46 int main() 47 { 48 //freopen("in.txt", "r", stdin); 49 ios::sync_with_stdio(false); 50 cin>>n>>q; 51 _rep(1,n){ 52 cin>>a[i]; 53 sum[i]=sum[i-1]+a[i]; 54 } 55 while(q--) 56 { 57 char cmd; int x,y; 58 cin>>cmd>>x>>y; 59 if(cmd=='Q') 60 printf("%I64d\n", sum[y]-sum[x-1]+range_ask(x,y)); 61 else 62 { 63 int z; cin>>z; 64 range_add(x, y, z); 65 } 66 } 67 return 0; 68 }
HDU 1698 (未解决)
题意:区间覆盖(不会),区间查询