1. 程式人生 > >逆序數《求所有子序列的逆序對個數的和

逆序數《求所有子序列的逆序對個數的和

題目

題解

一對逆序對對答案的貢獻是2^(n-2)
故統計出逆序對個數後乘上即可
注意序列長1的情況什麼什麼的
O( nlogn )

程式碼

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long int
#define mod 1000000007
LL a[1000005],b[1000005];
LL n;
LL ans;//極限情況500000*500000會爆,所以開LL
void mersort(LL x,LL y)
{
    if
(y-x<=1) return ; LL mid=(x+y)/2; mersort(x,mid); mersort(mid,y); LL p=x,i=x,q=mid; while(p<mid||q<y) { if(q==y||(p<mid&&a[p]<=a[q]))//注意,不是a[p]<=a[mid],弄清比較的物件 //x到y排序,所以應該和a[q]比,從而把後面的一到前面去。 b[i++]=a[p++]; else
if(p==mid||a[p]>a[q]) { if(p<mid) ans+=(mid-p); b[i++]=a[q++]; } } for(LL i=x; i<y; i++) a[i]=b[i]; } LL qu(LL a,LL b) { LL anss=1; while(b) { if(b&1) { anss=(anss*a)%mod; } b/=2
; a=(a*a)%mod; } return anss; } int main() { while(~scanf("%lld",&n)) { //if(n==1) continue; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); for(LL i=0; i<n; i++) scanf("%lld",&a[i]); ans=0; mersort(0,n); LL anss=qu(2,n-2); ans%=mod; printf("%lld\n",(ans*anss)%mod); } return 0; }