AtCoder Grand Contest 054 C Roughly Sorted
考虑一个合法的 \(P\),记 \(a_i = \sum\limits_{j=1}^{i-1} [P_j > P_i]\),则通过简单推理可得 \(a_i < a_{i+1} \Leftrightarrow P_i > P_{i+1}\)。易知一次合法交换操作 \((i,i+1)\) 当且仅当 \(a_i < a_{i+1} \land a_{i+1} > K\),否则就不能使得交换次数最小,并且交换后 \(a_i \gets a_i - 1\)。
现在已知 \(P'\),考虑求 \(b_i = \sum\limits_{j=1}^{i-1}[P'_j > P'_i]\),并且进行逆操作。因此一次交换操作 \((i,i+1)\) 合法当且仅当 \(b_i \ge b_{i+1} \land b_i \ge K\),且交换后 \(b_{i+1} \gets b_{i+1} + 1\)。逆序考虑所有满足 \(b_i = K\) 的 \(i\),则 \(P'_i\) 最多可以往右移 \(n-i\) 次,有 \(n-i+1\) 种选择。根据乘法原理易得答案为 \(\prod\limits_{b_i=K} (n-i+1)\)。
时间复杂度 \(O(n^2)\),若使用树状数组求 \(b\) 则复杂度降为 \(O(n \log n)\)。
code
// Problem: C - Roughly Sorted
// Contest: AtCoder - AtCoder Grand Contest 054
// URL: https://atcoder.jp/contests/agc054/tasks/agc054_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;
const int maxn = 5050;
const ll mod = 998244353;
int n, m, a[maxn], b[maxn];
void solve() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j < i; ++j) {
b[i] += (a[j] > a[i]);
}
}
ll ans = 1;
for (int i = 1; i <= n; ++i) {
if (b[i] == m) {
ans = ans * (n - i + 1) % mod;
}
}
printf("%lld\n", ans);
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}

浙公网安备 33010602011771号