zoukankan      html  css  js  c++  java
  • 树状数组求逆序对

    今天复习了一下树状数组,顺便学了一下如何求逆序对。

    首先是树状数组单点修改+区间和,但有一点需要注意,就是getsum函数里是now-=lowbit(now),但是update()里或add()里一定是now += lowbit(now);

    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int MAXN = 1e5 + 5;
    int n,c[MAXN],a[MAXN],m;
    int lowbit(int x)
    {
        return x & -x;
    }
    int getsum(int now)
    {
        int sum = 0;
        while(now > 0)
        {
            sum += c[now];
            now -= lowbit(now);
        }
        return sum;
    }
    void update(int l,int v)
    {
        while(l <= n)
        c[l] += v,l += lowbit(l);
    }
    /*int build_tree(int x)
    {
        int ret = 0;
        while(x > 0)
        {
            ret += c[pos];
            pos -= lowbit(pos);
        }
        return ret;
    }*/
    int main()
    {
        int c,d,e;
        cin>>n>>m;
        for(int i = 1;i <= n;i++)
        {
            cin>>a[i];
            update(i,a[i]);
        }
        for(int i = 1;i <= m;i++)
        {
            cin>>c>>d>>e;
            if(c == 1)
            {
                update(d,e);
            }
            else
            {
    //            cout<<getsum(e)<<" "<<getsum(d - 1)<<endl;
                cout<<getsum(e) - getsum(d - 1)<<endl;
            }
        }
        return 0;
    }

    然后是区间修改+单点求值,和单点修改有不同,主要是一开始不把数放进数组,然后假如要把d~f区间加上n,就先把d之后的都加上,然后减去f+1之后的就行了。

    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int MAXN = 1e7 + 5;
    int n,c[MAXN],a[MAXN],m,input[MAXN],g;
    int lowbit(int x)
    {
        return x & -x;
    }
    int getsum(int now)
    {
        int sum = 0;
        while(now > 0)
        {
            sum += c[now];
            now -= lowbit(now);
        }
        return sum;
    }
    void update(int l,int v)
    {
        while(l <= n)
        c[l] += v,l += lowbit(l);
    }
    /*int build_tree(int x)
    {
        int ret = 0;
        while(x > 0)
        {
            ret += c[pos];
            pos -= lowbit(pos);
        }
        return ret;
    }*/
    int main()
    {
        int d,e,f;
        cin>>n>>m;
        for(int i = 1;i <= n;i++)
        {
            cin>>a[i];
    //        update(i,a[i]);
        }
        for(int i = 1;i <= m;i++)
        {
            cin>>g;
            if(g == 1)
            {
                cin>>d>>e>>f;
                update(d,f);
                update(e + 1,-f);
            }
            else
            {
                cin>>d; 
                cout<<getsum(d) + a[d]<<endl;
            }
        }
        return 0;
    }

    最后,是求逆序对。先把这些数(结构体里再存一个编号)按照从大到小排序,(就算是离散化了,然后和原数就没关系了),然后向数组中插入编号,每次计算前面的和。注意,getsum里传入的是编号,而且必须传的是num-1.

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int c[40005],a[40005],n;
    struct node{
        int k,c;
    };
    node d[40055];
    int lowbit(int x)
    {
        return x & -x;
    }
    int getsum(int now)
    {
        int sum = 0;
        while(now > 0)
        {
            sum += c[now];
            now -= lowbit(now);
        }
        return sum;
    }
    int add(int now,int k)
    {
        while(now < n)
        {
            c[now] += k;
            now += lowbit(now);
        }
    }
    bool cmp(node x,node y)
    {
        return x.k > y.k;
    }
    int main()
    {
        int ans = 0;
        cin>>n;
        for(int i = 1;i <= n;i++)
        {
            d[i].c = i;
            cin>>d[i].k;
        }
        sort(d + 1,d + n + 1,cmp);
        for(int i = 1;i <= n;i++)
        {
            add(d[i].c,1);
            ans += getsum(d[i].c - 1);
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    javascript获取当前日期、年份和月份等
    程序员也可以懂一点期望值管理
    数据类型,隐式转换以及json,对象,引用类型,预解析 视频教程
    两个值交互位置的几种方法
    通过Class获取标签,兼容的几种思路
    前端开发流程
    元素多层嵌套,JS获取问题
    原生JS实现分页效果2.0(新增了上一页和下一页,添加当前元素样式)
    原生JS实现分页效果1.0
    学习方法,以及时间的安排。
  • 原文地址:https://www.cnblogs.com/DukeLv/p/8955842.html
Copyright © 2011-2022 走看看