1. 程式人生 > >樹狀陣列模版(單點修改區間求和)(區間修改單點求值)(區間修改區間求和)

樹狀陣列模版(單點修改區間求和)(區間修改單點求值)(區間修改區間求和)

eg。

hdu1166(單點修改區間求和)

#include<bits/stdc++.h>
#define maxn 111111
using namespace std;
int n;
int c[maxn];
int b[maxn];
int lowbit(int x) {
    return x&-x;
}
/**單點修改區間求和**/
/**
add(x,num);
sum(r)-sum(l-1);
每次x號位置修改num
求lr閉區間的和
**/

void add(int k,int num) {
    while(k<=n) {
        c[k]+=num;
        k+=lowbit(k);
    }
}
int sum(int k) {
    int ans=0;
    while(k) {
        ans+=c[k];
        k-=lowbit(k);
    }
    return ans;
}
int main()
{
    int t;
    int kase=0;
    scanf("%d",&t);
    while(t--) {
        memset(c,0,sizeof c);
        printf("Case %d:\n",++kase);
        scanf("%d",&n);
        int x,y;
        for(int i=1;i<=n;i++) {
            scanf("%d",&x);
            add(i,x);
        }
        char s[10];
        while(scanf("%s",s)&&strcmp(s,"End")!=0) {
            if(strcmp(s,"Query")==0) {
                scanf("%d%d",&x,&y);
                printf("%d\n",sum(y)-sum(x-1));
            }
            else {
                if(strcmp(s,"Add")==0) {
                    scanf("%d%d",&x,&y);
                    add(x,y);
                }
                else {
                    scanf("%d%d",&x,&y);
                    add(x,-y);
                }
            }
        }
    }
    return 0;
}
hdu 1556(區間修改單點求值)
#include<bits/stdc++.h>
#define maxn 111111
using namespace std;
int n;
int c[maxn];
int b[maxn];
int lowbit(int x) {
    return x&-x;
}
/**區間修改單點詢問**/
/**
add(l-1,-num);add(r,num);
sum(x);
每次修改閉區間lr的值,詢問x節點的值
**/

void add(int k,int num) {
    while(k) {
        b[k]+=num;
        k-=lowbit(k);
    }
}
int sum(int k) {
    int ans=0;
    while(k<=n) {
        ans+=b[k];
        k+=lowbit(k);
    }
    return ans;
}
int main()
{
     while(scanf("%d",&n)&&(n!=0)) {
        memset(b,0,sizeof b);
        int x,y;
        for(int i=1;i<=n;i++) {
            scanf("%d%d",&x,&y);
            add(x-1,-1);
            add(y,1);
        }
        for(int i=1;i<n;i++) {
            printf("%d ",sum(i));
        }
        printf("%d\n",sum(n));
     }





    return 0;
}

自己測試的(區間修改區間求和)
#include<bits/stdc++.h>
#define maxn 111111
using namespace std;
int n;
int c[maxn];
int b[maxn];
int lowbit(int x) {
    return x&-x;
}
/**區間修改區間求和**/
/**
add_b(r,num);add_c(r,num);
if(l>1) {
    add_b(l-1,-num);add_c(l-1,-num);
}
sum(r)-sum(l-1);
**/
void add_b(int x,int num) {
    for(int i=x;i>0;i-=lowbit(i))
        b[i]+=num;
}
void add_c(int x,int num) {
    for(int i=x;i<=n;i+=lowbit(i))
        c[i]+=x*num;
}
int sum_b(int x) {
    int ans=0;
    for(int i=x;i<=n;i+=lowbit(i))
        ans+=b[i];
    return ans;
}
int sum_c(int x) {
    int ans=0;
    for(int i=x;i>0;i-=lowbit(i))
        ans+=c[i];
    return ans;
}
int sum(int x) {
    if(x) return sum_b(x)*x+sum_c(x-1);
    else return 0;
}
int main()
{
    char s[10];
    memset(b,0,sizeof b);
    memset(c,0,sizeof c);
    scanf("%d",&n);
    while(scanf("%s",s)!=EOF) {
        int x,y,num;
        if(strcmp(s,"A")==0) {
            scanf("%d%d%d",&x,&y,&num);
            add_b(y,num);add_c(y,num);
            if(x>1) {
                add_b(x-1,-num);add_c(x-1,-num);
            }
        }
        else {
            scanf("%d%d",&x,&y);
            printf("%d\n",sum(y)-sum(x-1));
        }
        for(int i=1;i<=10;i++) {
            cout << b[i] << " ";
        }
        cout << endl;
        for(int i=1;i<=10;i++) {
            cout << c[i] << " ";
        }
        cout << endl;
    }
    return 0;
}