AGC030D Inversion Sum题解
洛谷题意传送门
题意
给你一个长度为 \(n\) 的数列,然后给你 \(q\) 个交换或不交换操作,你可以选择操作或者不操作,问所有情况下逆序对的总和。
\(n\le 3000,q\le 3000,A_i \le 10^9\)
题解
因为 \(n\) 比较小,所以考虑确定逆序对i,j的答案。
状态 \(dp[i][j]\) 表示 \(a[i]>a[j]\) 的方案数,随着 \(q\) 一个一个输入更新,但是不太行。
考虑把状态改成期望,之后 \(\times2^q\) 即可。
复杂度 \(O(n^2+n\times q)\)
代码
#include <bits/stdc++.h>
using namespace std ;
#define ll long long
#define rep(i,l,r) for(ll i=(l);i<=(r);++i)
#define per(i,r,l) for(ll i=(r);i>=(l);--i)
#define wif while
const ll inf = INT_MAX , df = 3005 , mod = 1e9 + 7 ;
ll i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,dp[df][df],a[df],ans ;
inline ll read() {
ll x = 0 , y = 1 ; char ch = getchar() ;
wif( ch > '9' || ch < '0' ) y = ( ch == '-' ) ? - 1 : 1 , ch = getchar() ;
wif( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar() ;
return x * y ; }
int main() {
n = read() , q = read() ; rep(i,1,n) a[i] = read() ;
rep(i,1,n) rep(j,1,n) dp[i][j] = ( a[i] > a[j] ) ;
ll inv2 = (mod+1) / 2 , cur = 1 ;
rep(i,1,q) {
cur *= 2 , cur %= mod ;
ll x = read() , y = read() ;
rep(j,1,n) {
if( j == x || j == y ) continue ;
ll ty = ( dp[x][j] + dp[y][j] ) % mod * inv2 % mod , tx = ( dp[j][x] + dp[j][y] ) % mod * inv2 % mod ;
dp[x][j] = dp[y][j] = ty ;
dp[j][x] = dp[j][y] = tx ;
}
ll ty = dp[x][y] + dp[y][x] ;
dp[x][y] = dp[y][x] = ty % mod * inv2 % mod ; }
rep(i,1,n-1) {
rep(j,i+1,n) ( ans += dp[i][j] ) %= mod ;
}
return printf("%lld\n",ans*cur%mod),0;
}

浙公网安备 33010602011771号