CodeForces 1730F Almost Sorted
过程相当于是将 重排列。设 为 中数为 的位置。考虑当前填的数 贡献的逆序对数,相当于是当前所有已经填入 的数 ,都有 的贡献。
考虑 意味着什么。
当正在填 时,之后还没填的数 ;当正在填 时,之前填了的数 。
综合一下就是,若考虑某个前缀已经填入 的状态,最小的还没填的数 最大的已经填了的数 。
由此可以想到状压。设 为当前最小的还没填的数为 , 的数的填入状态为 (填入为 ,没填入为 )。
转移枚举当前位填 ( 只能在 中),分开计算 的贡献和 的贡献即可。前部分预处理一个前缀有多少个 ,后部分暴力。然后还要计算,填了 后,新的最小的没填的数是多少。
时间复杂度 。
压行后是 CF 最短解。
code
// Problem: F. Almost Sorted // Contest: Codeforces - Codeforces Round 823 (Div. 2) // URL: https://codeforces.com/problemset/problem/1730/F // Memory Limit: 256 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 mkp make_pair #define mems(a, x) memset((a), (x), sizeof(a)) using namespace std; typedef long long ll; typedef double db; typedef unsigned long long ull; typedef long double ldb; typedef pair<ll, ll> pii; const int maxn = 5050; const int maxm = (1 << 9) + 9; int n, m, a[maxn], b[maxn], f[maxn][maxm], c[maxn][maxn]; void solve() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); b[a[i]] = i; } mems(f, 0x3f); f[0][0] = 0; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { c[i][j] = c[i - 1][j] + (j <= b[i]); } } for (int i = 0; i < n; ++i) { for (int S = 0; S < (1 << (m + 1)); ++S) { for (int j = 0; j <= m; ++j) { if (S & (1 << j)) { continue; } int t = c[i][b[i + j + 1]]; for (int k = 0; k <= m; ++k) { if (S & (1 << k)) { t += (b[i + k + 1] > b[i + j + 1]); } } int T = S | (1 << j), k = 0; while (k <= m && (T & (1 << k))) { ++k; } T >>= k; f[i + k][T] = min(f[i + k][T], f[i][S] + t); } } } printf("%d\n", f[n][0]); } int main() { int T = 1; // scanf("%d", &T); while (T--) { solve(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现