zoukankan      html  css  js  c++  java
  • 算法笔记--树状数组

    区间和模板:

    const int N=1e5+5;
    int c[N];
    int n;
    int lowbit(int x)
    {
        return x&(-x);
    }
    int sum(int x)
    {
        int ret=0;
        while(x)
        {
            ret+=c[x];
            x-=lowbit(x);
        }
        return ret;
    }
    void update(int x,int d)
    {
        while(x<=n)
        {
            c[x]+=d;
            x+=lowbit(x);
        }
    }

    1.单点更新,区间求和

    HDU - 1166

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e5+5;
    int c[N];
    int n;
    int lowbit(int x)
    {
        return x&(-x);
    }
    int sum(int x)
    {
        int ret=0;
        while(x)
        {
            ret+=c[x];
            x-=lowbit(x);
        }
        return ret;
    }
    void update(int x,int d)
    {
        while(x<=n)
        {
            c[x]+=d;
            x+=lowbit(x);
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int T,a,l,r;
        int cnt=0;
        string s;
        cin>>T;
        while(T--)
        {
            cin>>n;
            mem(c,0); 
            for(int i=1;i<=n;i++)cin>>a,update(i,a);
            cout<<"Case "<<++cnt<<":"<<endl;
            while(cin>>s)
            {
                if(s=="End")break;
                if(s=="Query")
                {
                    cin>>l>>r;
                    cout<<sum(r)-sum(l-1)<<endl;
                }
                else if(s=="Add")
                {
                    cin>>l>>r;
                    update(l,r);
                }
                else if(s=="Sub")
                {
                    cin>>l>>r;
                    update(l,-r);
                }
            } 
        }
        return 0;
    }
    View Code

    2.区间更新,单点求值

    有点像差分标记

    HDU - 1556

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e5+5;
    int c[N];
    int n;
    int lowbit(int x)
    {
        return x&(-x);
    }
    int sum(int x)
    {
        int ret=0;
        while(x)
        {
            ret+=c[x];
            x-=lowbit(x);
        }
        return ret;
    }
    void update(int x,int d)
    {
        while(x<=n)
        {
            c[x]+=d;
            x+=lowbit(x);
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int l,r;
        while(cin>>n)
        {
            mem(c,0);
            for(int i=1;i<=n;i++)
            {
                cin>>l>>r;
                update(l,1);
                update(r+1,-1);
            } 
            for(int i=1;i<=n;i++)
            {
                cout<<sum(i);
                if(i!=n)cout<<' ';
                else cout<<endl;
            } 
        }
        return 0;
    }
    View Code

    3.逆序数问题

    HDU - 2689

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e5+5;
    int c[N];
    int n;
    int lowbit(int x)
    {
        return x&(-x);
    }
    int sum(int x)
    {
        int ret=0;
        while(x)
        {
            ret+=c[x];
            x-=lowbit(x);
        }
        return ret;
    }
    void update(int x,int d)
    {
        while(x<=n)
        {
            c[x]+=d;
            x+=lowbit(x);
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t;
        while(cin>>n)
        {
            mem(c,0);
            int tot=0;
            for(int i=1;i<=n;i++)
            {
                cin>>t;
                update(t,1);
                tot+=i-sum(t);//sum(t)是小于等于t的个数 
            }
            cout<<tot<<endl;
        }
        return 0;
    }
    View Code

    HDU - 2838

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e5+5;
    int n;
    struct 
    {
        int cnt;
        ll sum;
    }c[N];
    int lowbit(int x)
    {
        return x&(-x);
    }
    ll _sum(int x)
    {
        ll ret=0;
        while(x)
        {
            ret+=c[x].sum;
            x-=lowbit(x);
        }
        return ret;
    }
    int cnt(int x)
    {
        int ret=0;
        while(x)
        {
            ret+=c[x].cnt;
            x-=lowbit(x);
        }
        return ret;
    }
    void update(int x,int d,int _d)
    {
        while(x<=n)
        {
            c[x].sum+=d;
            c[x].cnt+=_d;
            x+=lowbit(x);
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t;
        while(cin>>n)
        {
            for(int i=1;i<=n;i++)c[i].sum=c[i].cnt=0;
            ll sum=0;
            for(int i=1;i<=n;i++)
            {
                cin>>t;
                update(t,t,1);
                sum+=((ll)t*(i-cnt(t))+_sum(n)-_sum(t));
            }
            cout<<sum<<endl;
        }
        return 0;
    }
    View Code

    4.多维树状数组

    二维:

    HDU - 2642

    树状数组+容斥

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e3+5;
    int n;
    bool vis[N][N]={false};
    int c[N][N];
    int lowbit(int x)
    {
        return x&(-x);
    }
    void update(int x,int y,int d)
    {
        for(int i=x;i<N;i+=lowbit(i))
        {
            for(int j=y;j<N;j+=lowbit(j))
            {
                c[i][j]+=d;
            }
        }
    }
    int sum(int x,int y)
    {
        int ret=0;
        for(int i=x;i>0;i-=lowbit(i))
        {
            for(int j=y;j>0;j-=lowbit(j))
            {
                ret+=c[i][j];
            }
        }
        return ret;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int x,y,_x,_y;
        string s;
        while(cin>>n)
        {
            mem(c,0);
            mem(vis,false);
            for(int i=1;i<=n;i++)
            {
                cin>>s;
                if(s=="B")
                {
                    cin>>x>>y;
                    x++;
                    y++;
                    if(!vis[x][y])update(x,y,1),vis[x][y]=true;
                } 
                else if(s=="D")
                {
                    cin>>x>>y;
                    x++;
                    y++;
                    if(vis[x][y])update(x,y,-1),vis[x][y]=false;
                }
                else if(s=="Q")
                {
                    cin>>x>>_x>>y>>_y;
                    x++,y++,_x++,_y++;
                    if(x>_x)swap(x,_x);
                    if(y>_y)swap(y,_y);
                    cout<<sum(_x,_y)+sum(x-1,y-1)-sum(x-1,_y)-sum(_x,y-1)<<endl; 
                }
            }
        }
        return 0;
    }
    View Code

    三维:

    HDU - 3584

    区间更新,单点求值

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=105;
    int a[N][N][N];
    int n;
    int lowbit(int x)
    {
        return x&(-x);
    }
    void update(int x,int y,int z)
    {
        for(int i=x;i<=n;i+=lowbit(i))
        {
            for(int j=y;j<=n;j+=lowbit(j))
            {
                for(int k=z;k<=n;k+=lowbit(k))
                {
                    a[i][j][k]++;
                }
            }
        }
    }
    ll sum(int x,int y,int z)
    {
        ll res=0;
        for(int i=x;i>0;i-=lowbit(i))
        {
            for(int j=y;j>0;j-=lowbit(j))
            {
                for(int k=z;k>0;k-=lowbit(k))
                {
                    res+=a[i][j][k];
                }
            }
        }
        return res;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int x,y,z,_x,_y,_z;
        int t,m;
        while(cin>>n>>m)
        {
            mem(a,0);
            while(m--)
            {
                cin>>t;
                if(t)
                {
                    cin>>x>>y>>z>>_x>>_y>>_z;
                    update(x,y,z);
                    update(_x+1,y,z);
                    update(x,_y+1,z);
                    update(x,y,_z+1);
                    update(x,_y+1,_z+1);
                    update(_x+1,y,_z+1);
                    update(_x+1,_y+1,z);
                    update(_x+1,_y+1,_z+1); 
                }
                else
                {
                    cin>>x>>y>>z;
                    cout<<sum(x,y,z)%2<<endl;
                }
            }
        }
        return 0;
    } 
    View Code

    5.离散化树状数组

    POJ - 2299

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long 
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=5e5+10;
    struct node
    {
        int v;
        int id;
        bool operator < (const node t) const
        {
            return v<t.v;
        }
    }a[N];
    int mp[N];
    int c[N]; 
    int n;
    int lowbit(int x)
    {
        return x&(-x);
    }
    void update(int x,int d)
    {
        while(x<=n)c[x]+=d,x+=lowbit(x);
    }
    int sum(int x)
    {
        int res=0;
        while(x)res+=c[x],x-=lowbit(x);
        return res;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        while(cin>>n&&n)
        {
            mem(c,0);
            for(int i=1;i<=n;i++)
            {
                cin>>a[i].v;
                a[i].id=i;
            }
            sort(a+1,a+n+1);
            for(int i=1;i<=n;i++)mp[a[i].id]=i;
            ll ans=0;
            for(int i=1;i<=n;i++)
            {
                update(mp[i],1);
                ans+=i-sum(mp[i]);
            }
            cout<<ans<<endl;
        }
        return 0;
    } 
    View Code

    6.区间更新,区间查询

    不错的博客:https://www.cnblogs.com/lcf-2000/p/5866170.html

    模板:

    const int N=1e6+5;
    ll c1[N],c2[N];
    int n;
    void add(int x,int y)
    {
        for(int i=x;i<=n;i+=i&(-i))c1[i]+=y,c2[i]+=(ll)x*y;
    }
    ll sum(int x)
    {
        ll ans=0;
        for(int i=x;i>0;i-=i&(-i))ans+=c1[i]*(x+1)-c2[i];
        return ans;
    }

    http://codevs.cn/problem/1082/

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const int N=1e6+5;
    ll c1[N],c2[N];
    int n;
    void add(int x,int y)
    {
        for(int i=x;i<=n;i+=i&(-i))c1[i]+=y,c2[i]+=(ll)x*y;
    }
    ll sum(int x)
    {
        ll ans=0;
        for(int i=x;i>0;i-=i&(-i))ans+=c1[i]*(x+1)-c2[i];
        return ans;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t,q,a,b,x;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>t;
            add(i,t);
            add(i+1,-t);
        }
        cin>>q;
        while(q--)
        {
            cin>>t;
            if(t==1)
            {
                cin>>a>>b>>x;
                add(a,x);
                add(b+1,-x);
            }
            else if(t==2)
            {
                cin>>a>>b;
                cout<<sum(b)-sum(a-1)<<endl;
            }
        }
        //for(int i=1;i<=n;i++)cout<<c1[i]<<' '<<c2[i]<<endl;
        return 0;
    }
    View Code

    参考博客:http://blog.csdn.net/yexiaohhjk/article/details/51077545

  • 相关阅读:
    代理的原理
    nodemon:让node自动重启
    http与https的区别
    Content-Type:几种常用数据编码格式
    vue ssr服务端渲染
    vue 实现文件上传和文件下载
    vue element-ui表格里时间戳转换成时间显示
    vue npm start 自动打开网页
    yearProgress.vue
    vuejs中class与style的绑定
  • 原文地址:https://www.cnblogs.com/widsom/p/7749930.html
Copyright © 2011-2022 走看看