zoukankan      html  css  js  c++  java
  • ACM数据结构-树状数组

    模板:

    int n;
    int tree[LEN];
    
    int lowbit(int x){
        return x&-x;
    }
    
    void update(int i,int d){//index,delta
        while(i<=n){
            tree[i]+=d;
            i+=lowbit(i);
        }
    }
    
    int getsum(int i){
        int ans=0;
        while(i>0){
            ans+=tree[i];
            i-=lowbit(i);
        }
        return ans;
    }

    示意图:


    1.Ultra-QuickSort

    大佬代码:

        //树状数组  
        #include<iostream>  
        #include<string.h>  
        #include<algorithm>  
        using namespace std;  
        #define MAX 500010  
        int c[MAX];  
        int aa[MAX];  
        int n;  
        typedef struct nano{  
            int val;  
            int order;  
        }node;  
        node in[MAX];  
        int lowbit(int x)  
        {  
            return x&(-x);  
        }  
        void update(int x,int val)  
        {  
            while(x<=n){  
                c[x]+=val;  
                x+=lowbit(x);  
            }  
        }  
        int sum(int x)  
        {  
            int s=0;  
            while(x>=1)  
            {  
                s+=c[x];  
                x-=lowbit(x);  
            }  
            return s;//一开始竟然忘记写了这个语句,还以为树状数组写错了呢  
        }  
        bool cmp(node a,node b){  
            return a.val<b.val;  
        }  
        int main(int argc, char *argv[])  
        {  
            //freopen("2299.in", "r", stdin);  
            while(scanf("%d",&n)==1&&n){  
                for(int i=1;i<=n;++i)  
                {  
                    scanf("%d",&in[i].val);  
                    in[i].order=i;  
                }  
                sort(in+1,in+n+1,cmp);  
                for(int i=1;i<=n;++i)  
                    aa[in[i].order]=i;//离散化到小范围来  
                memset(c,0,sizeof(c));  
                long long ans=0;  
                for(int i=1;i<=n;++i)  
                {  
                    update(aa[i], 1);  
                    ans+=(i-sum(aa[i]));  
                }  
                printf("%lld
    ",ans);  
            }  
            return 0;  
        }  
    View Code

    大佬代码理解:

    首先用结构体node:{val,order} 来存输入信息,用sort(in+1,in+n+1,cmp); 来根据val值进行排序,通过代码

            for(int i=1;i<=n;++i)  
                aa[in[i].order]=i;

    构造数组aa,aa表示第i个数排第aa[i]位。(代码理解:i表示原本的索引,in[i].order表示排序后的索引)

    逆序数计算:

            for(int i=1;i<=n;++i)  
            {  
                update(aa[i], 1);  
                ans+=(i-sum(aa[i]));  
            }  

     ans增量: 索引i之前比他大的数。


    2.Mishka and Interesting sum

    大佬代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <map>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <algorithm>
    using namespace std;
    typedef  long long  ll;
    typedef unsigned long long ull;
    #define MM(a,b) memset(a,b,sizeof(a));
    #define inf 0x7f7f7f7f
    #define FOR(i,n) for(int i=1;i<=n;i++)
    #define CT continue;
    #define PF printf
    #define SC scanf
    const int mod=1000000007;
    const int N=1e6+100;
    int n,m,c[N],pre[N],sum[N],a[N],ans[N];
     
    struct node{
       int l,r,pos;
    }ne[N];
     
    int lowbit(int i)
    {
        return i&(-i);
    }
     
    void add(int p,int u)
    {
        while(p<=n)
        {
            c[p]^=u;
            p+=lowbit(p);
        }
    }
     
    int query(int u)
    {
       int res=0;
       while(u>=1)
       {
           res^=c[u];
           u-=lowbit(u);
       }
       return res;
    }
     
    bool cmp(node a,node b)
    {
        return a.r<b.r;
    }
     
    map<int,int> mp;
    int main()
    {
        while(~scanf("%d",&n))
        {
            MM(sum,0);MM(pre,0);MM(c,0);
            mp.clear();
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                sum[i]=sum[i-1]^a[i];
                if(mp[a[i]]) pre[i]=mp[a[i]];
                mp[a[i]]=i;
            }
            scanf("%d",&m);
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&ne[i].l,&ne[i].r);
                ne[i].pos=i;
            }
            sort(ne+1,ne+m+1,cmp);
            int i=1;
            for(int k=1;k<=m;k++)
            {
                for(;i<=ne[k].r;i++)
                {
                    if(pre[i]) add(pre[i],a[i]);
                    add(i,a[i]);
                }
                ans[ne[k].pos]=(query(ne[k].r)^query(ne[k].l-1)^sum[ne[k].r]^sum[ne[k].l-1]);
            }
            for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
        }
        return 0;
    }
    View Code

     3.模板编写训练1:P3368 【模板】树状数组 1

    代码:

    #include <stdio.h>
    #include <memory.h>
    #include <math.h>
    #include <string>
    #include <vector>
    #include <set>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <map>
    
    #define I scanf
    #define OL puts
    #define O printf
    #define F(a,b,c) for(a=b;a<c;a++)
    #define FF(a,b) for(a=0;a<b;a++)
    #define FG(a,b) for(a=b-1;a>=0;a--)
    #define LEN 500010
    #define MAX 1<<30
    #define V vector<int>
    #define ll long long  
    
    using namespace std;
    
    inline int read(){  
       int s=0,w=1;  
       char ch=getchar();  
       while(ch<='0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}  
       while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();  
       return s*w;  
    } 
    
    inline ll max(ll a,ll b){
        return a>b?a:b;
    }
    
    ll N;
    ll tree[LEN];
    
    int lowbit(int x){
        return -x&x;
    }
    
    ll getsum(int p){
        ll sum=0;
        while(p>0){
            sum+=tree[p];
            p-=lowbit(p);
        }
        return sum;
    }
    
    void update(int p,ll v){
        while(p<=N){
            tree[p]+=v;
            p+=lowbit(p);
        }
    }
    
    int main(){
    //    freopen("D:\CbWorkspace\ACM数据结构\树状数组\模板1.txt","r",stdin);
        int m,i,t,op;
        int a,b;
        scanf("%d%d",&N,&m);
        for(i=1;i<=N;i++){
            I("%d",&t);
            update(i,t);
        }
        for(i=1;i<=m;i++){
            I("%d%d%d",&op,&a,&b); 
            switch(op){
                case 1:
                    update(a,b);
                    break;
                case 2:
                    printf("%lld
    ",getsum(b)-getsum(a-1));
                    break;
            }
        }
        return 0;
    }
    View Code

    4.模板编写训练1:P3368 【模板】树状数组 2

    代码:

    #include <stdio.h>
    #include <memory.h>
    #include <math.h>
    #include <string>
    #include <vector>
    #include <set>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <map>
    
    #define I scanf
    #define OL puts
    #define O printf
    #define F(a,b,c) for(a=b;a<c;a++)
    #define FF(a,b) for(a=0;a<b;a++)
    #define FG(a,b) for(a=b-1;a>=0;a--)
    #define LEN 500010
    #define MAX 1<<30
    #define V vector<int>
    #define ll long long  
    
    using namespace std;
    
    inline int read(){  
       int s=0,w=1;  
       char ch=getchar();  
       while(ch<='0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}  
       while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();  
       return s*w;  
    } 
    
    inline ll max(ll a,ll b){
        return a>b?a:b;
    }
    
    ll N;
    ll tree[LEN];
    
    int lowbit(int x){
        return -x&x;
    }
    
    ll getsum(int p){
        ll sum=0;
        while(p>0){
            sum+=tree[p];
            p-=lowbit(p);
        }
        return sum;
    }
    
    void update(int p,ll v){
        while(p<=N){
            tree[p]+=v;
            p+=lowbit(p);
        }
    }
    
    int main(){
    //    freopen("D:\CbWorkspace\ACM数据结构\树状数组\模板2.txt","r",stdin);
        int m,i,t,op,pre=0;
        int a,b,c;
        scanf("%d%d",&N,&m);
        for(i=1;i<=N;i++){
            I("%d",&t);
            update(i,t-pre);
            pre=t;
        }
        for(i=1;i<=m;i++){
            I("%d",&op); 
            switch(op){
                case 1:
                    I("%d%d%d",&a,&b,&c); 
                    update(a,c);
                    update(b+1,-c);
                    break;
                case 2:
                    I("%d",&a); 
                    printf("%lld
    ",getsum(a));
                    break;
            }
        }
        return 0;
    }
    View Code

    注:使用差分数组

  • 相关阅读:
    go websocket
    go websocket 调试报错 request origin not allowed by Upgrader
    uniapp中使用阿里巴巴图标iconfont
    TS视频一
    ReactiveCocoa
    weak 的内部实现原理
    谈Objective-C block的实现
    基础面试总结
    理解 iOS 的内存管理
    URL Scheme
  • 原文地址:https://www.cnblogs.com/TQCAI/p/8453322.html
Copyright © 2011-2022 走看看