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); } }