维护转移位置的数组有点神。。
/* Telekinetic Forest Guard */
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 40005, inf = 0x3f3f3f3f;
int n, m, num[maxn], dp[maxn], pos[maxn], pre[maxn], cnt[maxn];
inline int iread() {
int f = 1, x = 0; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return f * x;
}
int main() {
n = iread(); m = iread();
for(int i = 1; i <= n; i++) num[i] = iread(), dp[i] = inf, pre[i] = -1;
n = unique(num + 1, num + 1 + n) - (num + 1);
m = sqrt(n);
dp[0] = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) if(pre[num[i]] <= pos[j]) cnt[j]++;
pre[num[i]] = i;
for(int j = 1; j <= m; j++) if(cnt[j] > j) {
int t = pos[j] + 1;
for(; pre[num[t]] > t; t++);
pos[j] = t; cnt[j]--;
}
for(int j = 1; j <= m; j++) dp[i] = min(dp[i], dp[pos[j]] + j * j);
}
printf("%d\n", dp[n]);
return 0;
}