树状数组模板题 hdu 1166
k为二进制末尾0的个数
树状数组 二进制 k 2k
tree[1] = A[1] 001 0 1
tree[2] = A[1] + A[2] 010 1 2
tree[3] = A[3] 011 0 1
tree[4] = A[1] +A[2] +A[3]+A[4] 100 2 4
tree[5] = A[5] 101 0 1
tree[6] = A[5] +A[6] 110 1 2
tree[7] = A[7] 111 0 1
tree[8] = A[1] +A[2] +A[3]+A[4]+A[5] +A[6] +A[7] +A[8] 1000 3 8
求和: 二进制
sum(1) = tree[1] 001 001
sum(2) = tree[2] 010 010
sum(3) = tree[3] + tree[2] 011 011 + 010
sum(4) = tree[4] 100 100
sum(5) = tree[5] + tree[4] 101 101 + 100
sum(6) = tree[6] + tree[4] 110 110 + 100
sum(7) = tree[7]+tree[6]+tree[4] 111 111 + 110 + 100
sum(8) = tree[8] 1000 1000
lowbit操作:
例如7
lowbit(7) = 1; cur + tree[7]
7 - 1 = 6;
lowbit (6) = 2; cur+ tree[6]
6 - 2 = 4;
lowbit(4) = 4; cur+ tree[4]
4 - 4 = 0;
代码:
#include <bits/stdc++.h> using namespace std; const int maxn = 50005; int tree[maxn]; int n; int lowbit(int x) { return x&(-x); } void add(int i,int value) //从叶子节点向上更新 例如 add(1,x) tree[001] -> tree[010] -> tree[100] 需要更新1->2->4 { // cout<<"***"<<endl; while(i<=n) { tree[i]+=value; i+=lowbit(i); } } int sum(int i) //从根节点向下加和 求sum(8) tree[1000] ;;;;; sum(7) tree[111]+tree[110]+tree[100] = tree7+tree6+tree4 { int cur = 0; while(i>0) { cur += tree[i]; i-=lowbit(i); } return cur; } int main() { int T; scanf("%d",&T); for(int i=1;i<=T;i++) { memset(tree,0,sizeof(tree)); scanf("%d",&n); for(int j=1;j<=n;j++) { int x; scanf("%d",&x); add(j,x); } printf("Case %d:\n",i); string s; while(cin>>s) { if(s=="End") break; else if(s=="Query") { int x,y; scanf("%d%d",&x,&y); printf("%d\n",sum(y)-sum(x-1)); } else if(s=="Add") { int pos,value; scanf("%d%d",&pos,&value); add(pos,value); } else if(s=="Sub"){ int pos,value; scanf("%d%d",&pos,&value); add(pos,-value); } } } return 0; }