[AGC030D] Inversion Sum 题解

很好的一道题。

思路#

由于 n 较小。

我们可以枚举位置 (i,j) 统计逆序对。

由于每次交换 (x,y) 只会影响与 x,y 有关的逆序对。

所以我们可以在修改的时候暴力修改。

但是这样有一个问题。

就是我们统计总和的时候,其他项应该需要乘二。

我们可能可以想到一些技巧性的方法比如整体打标记,给特殊项除二。

考虑我们实际统计的是什么。

是概率!

我们可以统计每一个逆序对出现的概率。

在最后面给答案乘上 2m 就是期望。

这也是期望与概率的互转。

如何 dp。

f1i,j 表示 ai<aj 的概率,f2i,j 表示 ai>aj 的概率。

转移比较简单,读者可以自行思考。

时间复杂度:O(n(n+q))

这道题其实有一个概率版本,CF258D。

Code#

/*
  ! Though life is hard, I want it to be boiling.
  ! Created: 2024/04/10 09:10:38
*/
#include <bits/stdc++.h>
using namespace std;

#define x first
#define y second
// #define int long long
#define mp(x, y) make_pair(x, y)
#define eb(...) emplace_back(__VA_ARGS__)
#define fro(i, x, y) for (int i = (x); i <= (y); i++)
#define pre(i, x, y) for (int i = (x); i >= (y); i--)
inline void JYFILE19();

typedef long long i64;
typedef pair<int, int> PII;

bool ST;
const int N = 3010;
const int mod = 1e9 + 7;
const int inv = 500000004;

i64 n, m, a[N], f1[N][N], f2[N][N];

signed main() {
  JYFILE19();
  cin >> n >> m;
  fro(i, 1, n) cin >> a[i];
  fro(i, 1, n) fro(j, i + 1, n) f1[i][j] = (a[i] < a[j]);
  fro(i, 1, n) fro(j, i + 1, n) f2[i][j] = (a[i] > a[j]);
  fro(i, 1, m) {
    int l, r;
    cin >> l >> r;
    if (l > r) swap(l, r);
    vector<int> fl1(n + 1);
    vector<int> fr1(n + 1);
    vector<int> fl2(n + 1);
    vector<int> fr2(n + 1);
    fro(j, 1, n) {
      if (j == l) continue;
      if (j < l) {
        fl1[j] = f1[j][r], fl2[j] = f2[j][r];
      } else if (j < r) {
        fl1[j] = f2[j][r], fl2[j] = f1[j][r];
      } else if (j > r) {
        fl1[j] = f1[r][j], fl2[j] = f2[r][j];
      }
    }
    fro(j, 1, n) {
      if (j == r) continue;
      if (j > r) {
        fr1[j] = f1[l][j], fr2[j] = f2[l][j];
      } else if (j > l) {
        fr1[j] = f2[l][j], fr2[j] = f1[l][j];
      } else if (j < l) {
        fr1[j] = f1[j][l], fr2[j] = f2[j][l];
      }
    }
    fl1[r] = f2[l][r], fl2[r] = f1[l][r];
    fro(j, 1, n) {
      if (j < r && j != l) f1[j][r] = (fr1[j] + f1[j][r]) % mod, f2[j][r] = (fr2[j] + f2[j][r]) % mod;
      if (j > r) f1[r][j] = (fr1[j] + f1[r][j]) % mod, f2[r][j] = (fr2[j] + f2[r][j]) % mod;
      if (j < l) f1[j][l] = (fl1[j] + f1[j][l]) % mod, f2[j][l] = (fl2[j] + f2[j][l]) % mod;
      if (j > l && j != r) f1[l][j] = (fl1[j] + f1[l][j]) % mod, f2[l][j] = (fl2[j] + f2[l][j]) % mod;
    }
    f1[l][r] = (fl1[r] + f1[l][r]) % mod;
    f2[l][r] = (fl2[r] + f2[l][r]) % mod;
  }
  int ans = 0;
  fro(i, 1, n) fro(j, i + 1, n) (ans += f2[i][j]) %= mod;
  cout << ans << "\n";
  return 0;
}

bool ED;
inline void JYFILE19() {
  // freopen("", "r", stdin);
  // freopen("", "w", stdout);
  srand(random_device{}());
  ios::sync_with_stdio(0), cin.tie(0);
  double MIB = fabs((&ED-&ST)/1048576.), LIM = 1024;
  cerr << "MEMORY: " << MIB << endl, assert(MIB<=LIM);
}

作者:JiaY19

出处:https://www.cnblogs.com/JiaY19/p/18211096

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   JiaY19  阅读(10)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示