• 树状数组求逆序对


    给定n个数,要求这些数构成的逆序对的个数。除了用归并排序来求逆序对个数,还可以使用树状数组来求解。
    树状数组求解的思路:开一个能大小为这些数的最大值的树状数组,并全部置0。从头到尾读入这些数,每读入一个数就更新树状数组,查看它前面比它小的已出现过的有多少个数sum,然后用当前位置减去该sum,就可以得到当前数导致的逆序对数了。把所有的加起来就是总的逆序对数。
    题目中的数都是独一无二的,这些数最大值不超过999999999,但n最大只是500000。如果采用上面的思想,必然会导致空间的巨大浪费,而且由于内存的限制,我们也不可能开辟这么大的数组。因此可以采用一种称为“离散化”的方式,把原始的数映射为1-n一共n个数,这样就只需要500000个int类型的空间。
    离散化的方式:
    struct Node
    {
    int v;
    int order;
    };
    Node node[500005];
    int reflect[500005];
    v存放原数组的元素,order存放原始位置,即Node[i].pos = i。
    把这些结构体按照val的大小排序。
    reflect数组存放离散化后的值,即reflect[Node[i].pos] = i。
    这样从头到尾读入reflect数组中的元素,即可以保持原来的大小关系,又可以节省大部分空间。

    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <algorithm>
    #include <string.h>
    using namespace std;
    const int maxn=500005;
    int n;
    int reflect[maxn]; //离散化后的数组
    int c[maxn];    //树状数组
    struct Node{
       int v;
       int order;
    }in[maxn];
    int lowbit(int x)
    {
        return x&(-x);
    }
    void update(int t,int value)
    {
        int i;
        for(i=t;i<=n;i+=lowbit(i))
        {
            c[i]+=value;
        }
    }
    int getsum(int x)
    {
        int i;
        int temp=0;
        for(i=x;i>=1;i-=lowbit(i))
        {
            temp+=c[i];
        }
        return temp;
    }
    bool cmp(Node a ,Node b)
    {
        return a.v<b.v;
    }
    int main()
    {
        int i,j;
        while(scanf("%d",&n)==1 && n)
        {
            //离散化
            for(i=1;i<=n;i++)
            {
                scanf("%d",&in[i].v);
                in[i].order=i;
            }
            sort(in+1,in+n+1,cmp);
            for(i=1;i<=n;i++) reflect[in[i].order]=i;
            //树状数组求逆序
            memset(c,0,sizeof(c));
            long long ans=0;
            for(i=1;i<=n;i++)
            {
                update(reflect[i],1);
                ans+=i-getsum(reflect[i]);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    刮开有奖
  • 相关阅读:
    (网络编程)基于tcp(粘包问题) udp协议的套接字通信
    (网络编程)理论 原理
    (网络编程) 介绍
    C++开源代码项目汇总
    Facial Landmark Detection
    人脸对齐ASM-AAM-CLM的一些总结
    Ello讲述Haar人脸检测:易懂、很详细、值得围观
    显示形状回归算法(ESR)代码介绍
    百度图像搜索探秘
    人脸特征点检测
  • 原文地址:https://www.cnblogs.com/xiaoningmeng/p/5967693.html
Copyright © 2020-2023  润新知