出题人的手环(求逆序对数)
题意:
出题人的妹子送了出题人一个手环,这个手环上有 n 个珠子,每个珠子上有一个数。
有一天,出题人和妹子分手了,想把这个手环从两个珠子间切开,并按顺时针顺序展开成一条链。
可以发现,这条链一共有 n 种可能性。求这 n 种可能性的逆序对数之积模 1000000007。
思路:
找出第一个排列的逆序对数(树状数组+离散化),之后每次将最后一个数减去比他大的,加上比他小的就是下一个序列的逆序对数。
WA点: 减去再加上之后的数 可能小于0,并且要long long
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include <cctype> 4 #include<algorithm> 5 #include<cstring> 6 #include<cmath> 7 #include<string> 8 #include<cmath> 9 #include<set> 10 #include<vector> 11 #include<stack> 12 #include<queue> 13 #include<map> 14 using namespace std; 15 #define ll long long 16 #define mem(a,x) memset(a,x,sizeof(a)) 17 #define se second 18 #define fi first 19 const ll mod=1e9+7; 20 const int INF= 0x3f3f3f3f; 21 const int N=2e5+5; 22 23 int a[N],c[N]; 24 int n; 25 struct node 26 { 27 int v,p; 28 }aa[N]; 29 30 bool cmp(node x,node y) 31 { 32 return x.v<y.v; 33 } 34 35 int lowbit(int i) { 36 return i&-i; 37 } 38 void add(int x,ll k) 39 { 40 for(int i=x;i<=n;i+=lowbit(i)) c[i]=(c[i]+k)%mod; 41 } 42 ll sum(ll x) 43 { 44 ll sum=0; 45 for(ll i=x;i>0;i-=lowbit(i)) sum=(sum+c[i])%mod; 46 return sum; 47 } 48 49 50 int main() 51 { 52 cin>>n; 53 for(int i=1;i<=n;i++) scanf("%lld",&aa[i].v),aa[i].p=i; 54 55 sort(aa+1,aa+1+n,cmp); 56 ll cnt=0; 57 for(int i=1; i<=n; i++) 58 { 59 if(aa[i].v != aa[i-1].v) { 60 cnt++; 61 } 62 a[aa[i].p] = cnt; 63 } 64 65 ll ans=0; 66 for(int i=1;i<=n;i++) 67 { 68 add(a[i],1); 69 ans = (ans+i-sum(a[i])+mod )%mod; 70 } 71 72 ll ans1=ans; 73 for(int i=1;i<n;i++) 74 { 75 ans=(ans-sum(a[i]-1) +mod )%mod; 76 ans=(ans+n-sum(a[i])+mod )%mod; 77 ans1=( ans1*ans) %mod; 78 } 79 printf("%lld\n",ans1); 80 }