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;
}

posted @ 2023-02-24 17:26  zltzlt  阅读(23)  评论(0)    收藏  举报