P3694 邦邦的大合唱站队 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll, i64;
const int N = 1e5 + 7;
int dp[1 << 20];
// dp[i]表示i状态下最少所需出队人数
// 此处之i状态指i的二进制下为1的队伍以从左到右的一定顺序排的状态
// 例如dp[1]指将第 一队所有成员排在整个队伍最左端所需最小出队人数
int sum[21][N];
// sum[j][k]表示第j队于初始队列前k个人中有多少人
int num[21];
// num[j]表示第j队总共有多少人
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
memset(dp, 63, sizeof(dp));
dp[0] = 0;
int n, m, c;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> c;
--c;
num[c]++;
for (int j = 0; j < m; j++) {
sum[j][i] = sum[j][i - 1];
}
sum[c][i]++;
}
int res = 0;
for (int i = 1, l, r; i < (1 << m); i++) {
res = 0;
for (int j = 0; j < m; j++) {
if (i & (1 << j)) {
res += num[j];
}
}
for (int j = 0; j < m; j++) {
if (i & (1 << j)) {
l = res - num[j];
r = res;
dp[i] = min(dp[i], dp[i^(1<<j)]+(r-l)-(sum[j][r]-sum[j][l]));
}
}
}
cout << dp[(1 << m) - 1];
return 0;
}