zoukankan      html  css  js  c++  java
  • 树状数组

    树状数组常数比线段树小很多啊……还好写……有必要总结一下。

    单点修改,区间查询

    不废话,代码:

    #include <cstdio>
    using namespace std;
    int q,x,y;
    int n,m,a[500005],c[500005];
    void update(int x,int k)
    {
        while(x<=n) c[x]+=k, x+=x&(-x);
    }
    int query(int x)
    {
        int sum=0;
        while(x>0) sum+=c[x], x-=x&(-x);
        return sum;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
            update(i,a[i]);
        }
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d%d",&q,&x,&y);
            if(q==1) update(x,y);
            if(q==2) printf("%d
    ",query(y)-query(x-1));
        }
        return 0;
    }
    

    区间修改,单点查询

    考虑使用差分建立树状数组,修改时只需修改区间边界,查询时求前缀和即可。

    #include <cstdio>
    using namespace std;
    int q,x,y,k;
    int n,m,a[500005],c[500005];
    void update(int x,int k)
    {
        while(x<=n) c[x]+=k, x+=x&(-x);
    }
    int query(int x)
    {
        int sum=0;
        while(x>0) sum+=c[x], x-=x&(-x);
        return sum;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
            update(i,a[i]-a[i-1]);
        }
        for(int i=1;i<=m;++i)
        {
            scanf("%d",&q);
            if(q==1) 
            {
                scanf("%d%d%d",&x,&y,&k); 
                update(x,k); 
                update(y+1,-k);
            }
            if(q==2)
            {
                scanf("%d",&x);
                printf("%d
    ",query(x));
            }
        }
        return 0;
    }
    

    区间修改,区间查询

    这里详细说一下。
    首先我们要求 (sumlimits_{i = 1}^n {{a_i}}) ,即 $sumlimits_{i = 1}^n {sumlimits_{j = 1}^i {{c_j}} } $ ,把这个式子变换一下,得到这样的一坨:$$nsumlimits_{i = 1}^n {{c_i} - sumlimits_{i = 1}^n {(i - 1){c_i}} } $$ 于是,我们就可以维护两个树状数组,查询时求差值即可。
    注意建数组时也要稍微改改。
    代码代码代码:

    #include <cstdio>
    using namespace std;
    int q,x,y,k;
    int m,n,a[100005],s1[100005],s2[100005];
    void update(int i,int k)
    {
        int x=i;
        while(i<=n) s1[i]+=k, s2[i]+=(x-1)*k, i+=i&(-i);
    }
    int query(int i)
    {
        int sum=0, x=i;
        while(i>0) sum+=s1[i]*x-s2[i], i-=i&(-i);
        return sum;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
            update(i,a[i]-a[i-1]);
        }
        for(int i=1;i<=m;++i)
        {
            scanf("%d",&q);
            if(q==1)
            {
                scanf("%d%d%d",&x,&y,&k);
                update(x,k); update(y+1,-k);
            }
            if(q==2)
            {
                scanf("%d%d",&x,&y);
                printf("%d
    ",query(y)-query(x-1));
            }
        }
        return 0;
    }
    

    注意有的时候要开long long。

  • 相关阅读:
    微信小程序 单选按钮 最佳
    微信小程序 单选按钮的实现
    微信小程序 单选框实现
    Java Code To Create Pyramid and Pattern
    Java language
    npm Err! Unexpected end of JSON input while parsing near
    Node.js Express FrameWork Tutorial
    Higher-Order Function Examples
    Create First HTTP Web Server in Node.js: Complete Tutorial
    Node.js NPM Tutorial: Create, Publish, Extend & Manage
  • 原文地址:https://www.cnblogs.com/wzzyr24/p/11487954.html
Copyright © 2011-2022 走看看