树状数组模板题 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;
}

 

posted @ 2019-01-13 17:59  zangzang  阅读(155)  评论(0编辑  收藏  举报