XDU1024简单逆序对(贪心||分治)

题目描述

逆序对问题对于大家来说已经是非常熟悉的问题了,就是求i<j时,a[i] > a[j]的组数。现在请你求出一串数字中的逆序对的个数,需要注意的是,这些数字均在[0,9]之内。

输入

第一行输入T,表示有T组测试数据
对于每组数据,首先输入n,代表有n个数(0<n<=10^6)
接下来输入n个数,每个数都在[0,9]之内

输出

输出逆序对的个数,且对10^9+7取模

样例输入

2
3
3 2 1
3
1 2 1

样例输出

3
1

解法一:数学贪心解法(有点小技巧哦)

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int d[10];
int main()
{
    int T,n;
    cin>>T;
    while(T--){
        cin>>n;
        int ans=0,arr[n];
        memset(d,0,sizeof(d));
        memset(arr,0,sizeof(arr));
        for(int i=1;i<=n;i++) cin>>arr[i];
        for(int i=1;i<=n;i++){
            int res=0;
            d[arr[i]]++;
            for(int j=arr[i]+1;j<=9;j++)
                res=(res+d[j])%mod;
            ans=(ans+res)%mod;
        }
        cout<<ans<<endl;
    } 
} 

解法二:分治(和归并排序类似吧感觉)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
const int mod=1e9+7;
int ans;
int a[maxn],c[maxn];
void Conquer_Divide(int l,int r)
{
    int m=(l+r)/2;
    if(r>l){
        Conquer_Divide(l,m);
        Conquer_Divide(m+1,r);
        int i=l,j=m+1,t=l;
        while(i<=m&&j<=r){
            if(a[i]>a[j]){
                c[t++]=a[j++];
                ans=(ans+m-i+1)%mod;
            }
            else c[t++]=a[i++];
        }
        while(i<=m) c[t++]=a[i++];
        while(j<=r) c[t++]=a[j++];
        for(i=l;i<=r;i++) a[i]=c[i];
    }
}
int main()
{
    int n,T;
    cin>>T;
    while(T--){
        cin>>n;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        ans=0;
        Conquer_Divide(1,n);
        printf("%d\n",ans);
    }
}

 

posted @ 2017-04-21 16:56  despair_ghost  阅读(371)  评论(0编辑  收藏  举报