zoukankan      html  css  js  c++  java
  • 【数据结构】树状数组【模板】

    证明什么的待补

    一维

    问题 E: 单点修改,区间查询

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long  ll;
    const int N=1e6+7;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    ll a[N],c[N],n;
    inline int lowbit(int x){
        return x&-x;
    }
    inline void add(int i,int x){
        while(i<=n){
            c[i]+=x;
            i+=lowbit(i);
        }
        return ;
    }
    inline ll  sum(int i){
        ll  res=0;
        while(i){
            res+=c[i];
            i-=lowbit(i);
        }
        return res;
    }
    int main(){
        int q;
        n=read();q=read();
        for(int i=1;i<=n;i++){
            int x;
            x=read();
            add(i,x);
        }
        while(q--){
            int l,r,w;
            w=read();l=read();r=read();
            if(w==1) add(l,r);
            else {
                    ll res=sum(r)-sum(l-1);
                    printf("%lld
    ",res);
            }
        }
        return 0;
    }
    

    问题 F: 区间修改,单点查询

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e6+7;
    ll a[N],c[N];//原数组和树状数组
    ll n;
    inline ll read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline ll lowbit(ll x){
        return x&-x;
    }
    void add(ll i,ll k){
        while(i<=n){
            c[i]+=k;
            i+=lowbit(i);
        }
    }
    ll sum(ll i){//求a[1]到a[n]的和
        ll res=0;
        while(i>0){
            res+=c[i];
            i-=lowbit(i);
        }
        return res;
    }
    int main(){
        ll q,x;
        n=read();q=read();
        for(ll i=1;i<=n;i++){
            a[i]=read();
            add(i,a[i]-a[i-1]);
        }
     
        while(q--){
            ll a,b,c,d;
            a=read();
            if(a==1){
               b=read();c=read();d=read();
                add(b,d);
                add(c+1,-d);
            }
            else{
               b=read();
                printf("%lld
    ",sum(b));
            }
        }
        return 0;
    }
    

    问题 G: 区间修改,区间查询

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e6+7;
    ll a[N],sum1[N],sum2[N];
    ll n,m;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline ll lowbit(ll x){
        return x&-x;
    }
    inline void update(ll i,ll k){
        ll x=i;
        while(i<=n){
            sum1[i]+=k;
            sum2[i]+=k*(x-1);
            i+=lowbit(i);
        }
    }
    inline ll sum(int i){
        ll res=0,x=i;
        while(i>0){
            res+=x*sum1[i]-sum2[i];
            i-=lowbit(i);
        }
        return res;
    }
    int main(){
        n=read();m=read();
        for(ll i=1;i<=n;i++){
            cin>>a[i];
            update(i,a[i]-a[i-1]);
        }
        while(m--){
            ll k,l,r,x;
            k=read();
            if(k==1){
                l=read();r=read();x=read();
                update(l,x);
                update(r+1,-x);
            }
            else{
                l=read();r=read();
                ll res=sum(r)-sum(l-1);
                printf("%lld
    ",res);
            }
        }
        return 0;
    }
    

    二维

    问题 H: 单点修改,区间查询

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=5500;
    ll a[N][N],n,m;
    inline ll read()
    {
        ll x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    ll lowbit(ll x){
        return x&-x;
    }
    void update(ll x,ll y,ll v){
        for(int i=x;i<=n;i+=lowbit(i))
            for(int j=y;j<=m;j+=lowbit(j))
                a[i][j]+=v;
    }
    ll sum(ll x,ll y){
        ll res=0;
        for(int i=x;i>0;i-=lowbit(i))
            for(int j=y;j>0;j-=lowbit(j))
                res+=a[i][j];
        return res;
    }
    ll query(ll x1,ll y1,ll x2,ll y2){
        return sum(x1,y1)-sum(x1,y2-1)-sum(x2-1,y1)+sum(x2-1,y2-1);
    }
    int main(){
        while(~scanf("%d%d",&n,&m)){
            memset(a,0,sizeof a);
            int op;
            while(~scanf("%d",&op)){
                if(op==1){
                    ll x,y,k;
                    x=read();y=read();k=read();
                    //cin>>x>>y>>k;
                    update(x,y,k);
                }
                else{
                    ll a,b,c,d;
                    c=read();d=read();a=read();b=read();
                    //cin>>a>>b>>c>>d;
                    printf("%lld
    ",query(a,b,c,d));
                }
            }
        }
        return 0;
    }
    

    问题 I: 区间修改,区间查询

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=2100;
    ll t1[N][N],t2[N][N],t3[N][N],t4[N][N];
    ll n,m;
    ll lowbit(ll x){
        return x&(-x);
    }
    void add(ll x,ll y,ll v){
        for(ll i=x;i<=n;i+=lowbit(i))
            for(ll j=y;j<=m;j+=lowbit(j)){
                t1[i][j]+=v;
                t2[i][j]+=v*x;
                t3[i][j]+=v*y;
                t4[i][j]+=v*x*y;
            }
    }
    void update(ll x1,ll y1,ll x2,ll y2,ll v){
        add(x1,y1,v);
        add(x1,y2+1,-v);
        add(x2+1,y1,-v);
        add(x2+1,y2+1,v);
    }
    ll sum(ll x,ll y){
        ll res=0;
        for(ll i=x;i>0;i-=lowbit(i))
            for(ll j=y;j>0;j-=lowbit(j))
                res+=(x+1)*(y+1)*t1[i][j]-(y+1)*t2[i][j]-(x+1)*t3[i][j]+t4[i][j];
        return res;
    }
    ll query(ll x1,ll y1,ll x2,ll y2){
        return sum(x2,y2)+sum(x1-1,y1-1)-sum(x2,y1-1)-sum(x1-1,y2);
    }
    int main(){
        scanf("%lld%lld", &n, &m);
        int op;
        while(~scanf("%d",&op)){
            if(op==1){
                ll a,b,c,d,x;
                 scanf("%lld%lld%lld%lld%lld", &a, &b, &c, &d, &x);
               // a=read();b==read();c=read();d=read();x=read();
                update(a,b,c,d,x);
            }
            else{
                ll a,b,c,d;
                 scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
                //a=read();b==read();c=read();d=read();
                printf("%lld
    ",query(a,b,c,d));
            }
        }
        return 0;
    }
    

    参考博客:树状数组详解 - Xenny - 博客园 (吹爆这篇!)
    彻底弄懂二维树状数组_ó-CSDN博客
    二维树状数组总结及模板_kangdi的博客-CSDN博客

  • 相关阅读:
    http://blog.csdn.net/zhang_xinxiu/article/details/38655311
    三分钟了解Activity工作流
    在eclipse中设计BPMN 2.0工作流定义的根本步骤
    http://blog.csdn.net/bluejoe2000/article/details/39521405#t9
    activity的测试工程activiti-explorer使用
    如何让Activiti-Explorer使用sql server数据库
    Java中对List集合排序的两种方法
    常用 Git 命令清单
    推荐!手把手教你使用Git
    理解RESTful架构
  • 原文地址:https://www.cnblogs.com/OvOq/p/14853216.html
Copyright © 2011-2022 走看看