51Nod1019题(逆序数)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51Nod1019题(逆序数)相关的知识,希望对你有一定的参考价值。

最开始不知道归并排序,于是这道题就各种花式T,最好的一次1015ms,也是醉了。

说下最开始的想法:   用<set>插入第一个数,随后输入的数依次比较<set>中的元素,如果与其中 <= 其中一个数,

则后面的数都可作为其逆序数,用  “<set>当前容量” 减去 “当前数的位置” 就是这个数所产生的逆序数对数,最后插入该数,

还是粘一下代码吧(TLE)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
#include <climits>
#include <cmath>
#define maxn 400000
using namespace std;

int main()
{
    //freopen("lxx.txt","r",stdin);
    int i,j,group;
    char ch;
    while(scanf("%d",&group)!=EOF)
    {
        set<int>s;
        set<int>::iterator it;
        int d[group],a[group];
        scanf("%d",&a[0]);
        s.insert(a[0]);
        int ans=0;
        for(i=1; i<group; ++i)
        {
            scanf("%d",&a[i]);
            int cnt=0;  //记录当前数在set中遍历时所在位置
            for(it=s.begin(); it!=s.end(); ++it)
            {
                if(a[i]<=*it)
                {
                    ans+=(s.size()-cnt);
                    break;
                }
                ++cnt;
            }
            s.insert(a[i]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

 然后再说下AC想法,其实就是归并排序的简单应用(归并排序 时间复杂度nlogn 空间n 且稳定)

归并算法网上讲的很多也很全面,这就不说了。

这个题只是注意下每次判断到符合条件时,cnt(总逆序数)加的个数

#include<iostream>
#include<sstream>
#include<stack>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<cctype>
#include<queue>
#include<algorithm>
#include<cmath>
#include<map>                          //AC 140ms  2452KB
#include<set>                     
#define inf 0x3f3f3f3f
#define N 50001

using namespace std;

int a[N],temp[N];
int cnt;
void mer(int x,int mid,int y)   //合并过程
{
    int i=x;
    int j=mid+1;
    int k=0;
    while(i<=mid&&j<=y)
    {
        if(a[i]<=a[j]) temp[k++]=a[i++];
        else {temp[k++]=a[j++]; cnt+=(mid+1-i);}
        //这里是mid+1-i,而不是j-i,主要是j-i会重复统计逆序数(mid+1到j在之前递归时已经统计过了)
    }
    while(i<=mid) temp[k++]=a[i++];
    while(j<=y) temp[k++]=a[j++];
    for(i=0; i<k; ++i) a[x+i]=temp[i];  
}

void mergesort(int x,int y)
{
    if(x<y)
    {
        int mid=x+((y-x)>>1);
        mergesort(x,mid);
        mergesort(mid+1,y);
        mer(x,mid,y);
    }
}

int main()
{
    int n,i,j;
   // freopen("lxx.txt","r",stdin);
    while(scanf("%d",&n)!=EOF)
    {
        cnt=0;
        for(i=0; i<n; ++i)
        {
            scanf("%d",&a[i]);
        }
        mergesort(0,n-1);
        printf("%d\n",cnt);
    }
    return 0;
}

 

以上是关于51Nod1019题(逆序数)的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1019 逆序数

逆序数 51nod 1019 归并 分治

51Nod 1019 逆序数 (归并排序)

51nod 1020 逆序排列

51nod 1020 逆序排列 递推DP

51nod 1107(树状数组逆序数)