正题
题目链接:https://atcoder.jp/contests/agc030/tasks/agc030_d
题目大意
nnn个数,ppp次操作可以选择操作或者不操作,询问所有情况下逆序对的总和。
解题思路
转换成期望的问题,设fi,jf_{i,j}fi,j表示所有情况下ai<aja_i<a_jai<aj的情况,那么对于每次操作有12\frac{1}{2}21的概率交换和不交换,可以用dpdpdp转移。最后答案乘上2q2^q2q即可。
时间复杂度O(n2+nq)O(n^2+nq)O(n2+nq)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=3100,XJQ=1e9+7;
ll n,q,a[N],f[N][N],g[N][N];
int main()
{scanf("%lld%lld",&n,&q);for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);for(ll i=1;i<=n;i++)for(ll j=1;j<=n;j++)f[i][j]=(a[i]<a[j]);ll inv=(XJQ+1)/2,k=1;while(q--){ll l,r;k=k*2%XJQ;scanf("%lld%lld",&l,&r);f[l][r]=f[r][l]=(f[l][r]+f[r][l])*inv%XJQ;for(ll i=1;i<=n;i++){if(i==l||i==r)continue;f[i][l]=f[i][r]=(f[i][r]+f[i][l])*inv%XJQ;f[l][i]=f[r][i]=(f[r][i]+f[l][i])*inv%XJQ;}}ll ans=0;for(ll i=1;i<=n;i++)for(ll j=1;j<i;j++)(ans+=f[i][j])%=XJQ;printf("%lld",ans*k%XJQ);
}