树状数组模版

转 大神 :http://blog.csdn.net/acmmmm/article/details/9850687

一维数组数组形式

int c[N], maxn;  
inline int Lowbit(int x){return x&(-x);}  
void change(int i, int x)//i点增量为x  
{  
    while(i <= maxn)  
    {  
        c[i] += x;  
        i += Lowbit(i);  
    }  
}  
int sum(int x){//区间求和 [1,x]  
    int ans = 0;  
    for(int i = x; i >= 1; i -= Lowbit(i))  
        ans += c[i];  
    return ans;  
}  

求区间最值

struct Tree{  
    //手动初始化num数组  
    int lowbit(int x){ return x&(-x); }  
    int a[100005], num[100005], maxn;  
    void init(int len){  
        maxn = len;  
        for (int i = 1; i <= maxn; i++){  
            a[i] = num[i];  
            for (int j = 1; j < lowbit(i); j <<= 1)  
                a[i] = min(a[i], a[i - j]);  
        }  
    }  
    void updata(int pos, int val){  
        num[pos] = val;  
        for (int i = pos; i <= maxn; i += lowbit(i)){  
            a[i] = val;  
            for (int j = 1; j < lowbit(i); j <<= 1)  
                a[i] = min(a[i], a[i - j]);  
        }  
        return;  
    }  
    int query(int l, int r){  
        int ans = num[r];  
        while (true){  
            ans = min(ans, num[r]);  
            if (r == l) break;  
            for (r -= 1; r - l >= lowbit(r); r -= lowbit(r))  
                ans = min(ans, a[r]);  
        }  
        return ans;  
    }  
}tree;  

改段求段模版:

const int N = 4e5 + 100;  
template<class T>  
struct Tree{  
    T c[2][N];  
    int maxn;  
    void init(int x){  
        maxn = x+10; memset(c, 0, sizeof c);  
    }  
    inline int lowbit(int x){ return x&-x; }  
    T sum(T *b, int x){  
        T ans = 0;  
        if (x == 0)ans = b[0];  
        while (x)ans += b[x], x -= lowbit(x);  
        return ans;  
    }  
    void change(T *b, int x, T value){  
        if (x == 0)b[x] += value, x++;  
        while (x <= maxn)b[x] += value, x += lowbit(x);  
    }  
    T get_pre(int r){  
        return sum(c[0], r) * r + sum(c[1], r);  
    }  
    void add(int l, int r, T value){//区间加权  
        change(c[0], l, value);  
        change(c[0], r + 1, -value);  
        change(c[1], l, value * (-l + 1));  
        change(c[1], r + 1, value * r);  
    }  
    T get(int l, int r){//区间求和  
        return get_pre(r) - get_pre(l - 1);  
    }  
};  
Tree<ll> x, y;  

逆向使用时:

int c[N], maxn;  
inline int Lowbit(int x){return x&(-x);}  
int sum(int i)//单点更新i点改为x  
{  
    int ans = 0;  
    while(i <= maxn)  
    {  
        ans += c[i];  
        i += Lowbit(i);  
    }  
    return ans;  
}  

void change(int x, int value){//[1,x]增量为value  
    for(int i = x; i >= 1; i -= Lowbit(i))  
        c[i] += value;  
}  

树状数组求逆序数:
4 3 1 2
i = 1 : 插入4 : update(4,1),sum(4)返回1,那么当前比4大的为i - 1 = 0;
i = 2 : 插入3 : update(3,1),sum(3)返回1,那么当前比3大的为i - 1 = 1;
i = 3 : 插入1 : update(1,1),sum(1)返回1,那么当前比1大的为i - 1 = 2;
i = 4 : 插入2 : update(2,1),sum(2)返回2,那么当前比2大的为i - 2 = 2;

//逆序数  
#include<stdio.h>  
#include<string.h>  
#include<stdlib.h>  
#include<algorithm>  
using namespace std;  
const int N=1000005;  
#define LL __int64  
LL cal[N],res[N],ans,ros[N];  
LL n,maxn,minm;  
int lowbit(int x) {return x&-x;}  
LL getsum(int x) {  
    LL s=0;  
    for(;x>0;s+=cal[x],x-=lowbit(x));  
    return s;  
}  
void update(int x,int value) {  
    for(;x<=maxn;cal[x]+=value,x+=lowbit(x));  
}  
int find(int value) {  
    int l=1,r=maxn,mid;  
    while(l<=r) {  
        mid=(l+r)>>1;  
        if(ros[mid]==value) return mid;  
        else if(ros[mid]>value) r=mid-1;  
        else l=mid+1;  
    }  
    return -1;  
}  
int main() {  
    int i,j,k;  
    LL total;  
    while(~scanf("%d",&n)) {  
        for(i=1;i<=n;i++) {  
            scanf("%I64d",&res[i]);  
            ros[i]=res[i];  
        }  
        memset(cal,0,sizeof(cal));  
        sort(ros+1,ros+n+1);  
        for(j=1,i=2;i<=n;i++) {  
            if(ros[i]!=ros[j]) ros[++j]=ros[i];  
        }  
        maxn=j;  
        for(i=1,total=0;i<=n;i++) {  
            k=find(res[i]);  
            update(k,1);  
            total+=i-getsum(k);  
        }  
        printf("%I64d\n",total);  
    }  
    return 0;  
}  
/*  
3 3 1 2   
ans=2 
  */

二维树状数组支持对矩阵的子块操作,单点操作,子块求和

const int MAX=1200;  
int c[MAX][MAX];  
int n;  
int LowBit(int t){ return t&(-t);}  
int Sum(int endx,int endy)//求和  求矩阵[1,1]-[endx,endy]的和  
{  
    int sum=0;  
    int temp=endy;  
    while(endx>0)  
    {  
        endy=temp;//  
        while (endy>0)  
        {  
            sum+=c[endx][endy];  
            endy-=LowBit(endy);  
        }  
        endx-=LowBit(endx);  
    }  
    return sum;  
}  
void add(int addx,int addy,int num)//在[x,y]位置上加上 num  
{  
    int temp=addy;  
    while (addx <=n)  
    {  
        addy=temp;  
        while(addy<=n)  
        {  
            c[addx][addy]+=num;  
            addy+=LowBit(addy);  
        }  
        addx+=LowBit(addx);  
    }  
}  
int GetSum(int l,int b,int r,int t)//求[l,b]-[r,t]的和  若是点 则是GetSum(x,y,x,y)  

{  
    return Sum(r,t)-Sum(r,b-1)-Sum(l-1,t)+Sum(l-1,b-1);  
}  
void updat(int x,int y,int val){        //更新[1,1]-[x,y]区间的点  都+val  
        for (;x<=n;x+=LowBit(x))  
         for (int i=y;i<=n;i+=LowBit(i))  
             c[x][i]+=val;  

}  
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);  
            x2++,y2++;
            updat(x1, y1, 1);  
            updat(x2 , y2, -1);  
            updat(x1, y2 , -1);  
            updat(x2 , y1, -1);  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值