令$f[i]$表示以i为结尾的答案最小值,则$f[i] = min \{f[j] + cnt[j + 1][i]^2\}_{1 \leq j < i}$,其中$cnt[j + 1][i]$表示$[j + 1, i]$内有几个不同的数
对于区间长度为$k$,则答案最大值就是$\sqrt{k}$,所以对于每个$i$我们其实只要枚举$\sqrt{i}$个值就好了
1 /************************************************************** 2 Problem: 1584 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:112 ms 7 Memory:1120 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 const int N = 4e4 + 5; 15 const int MXlen = 250; 16 17 int n, m; 18 int a[N], f[N], seq[MXlen], now[MXlen]; 19 int st, mxlen, nowlen; 20 21 inline int read(); 22 23 inline int sqr(int x) { 24 return x * x; 25 } 26 27 int main() { 28 int i, j; 29 n = read(), m = read(); 30 for (i = 1; i <= n; ++i) a[i] = read(); 31 for (mxlen = 1; mxlen * mxlen <= n; ++mxlen); 32 --mxlen; 33 for (i = 1; i <= n; ++i) { 34 f[i] = i; 35 for (st = 0, j = 1; j <= nowlen; ++j) 36 if (seq[j] == a[i]) { 37 st = j; 38 break; 39 } 40 if (!st) { 41 if (nowlen != mxlen) { 42 seq[++nowlen] = a[i]; 43 now[nowlen] = i; 44 } else { 45 for (j = 1; j < nowlen; ++j) 46 seq[j] = seq[j + 1], now[j] = now[j + 1]; 47 seq[nowlen] = a[i], now[nowlen] = i; 48 } 49 } else { 50 for (j = st; j < nowlen; ++j) 51 seq[j] = seq[j + 1], now[j] = now[j + 1]; 52 seq[nowlen] = a[i], now[nowlen] = i; 53 } 54 for (j = nowlen; j >= 2; --j) 55 f[i] = min(f[i], f[now[j - 1]] + sqr(nowlen - j + 1)); 56 } 57 printf("%d\n", f[n]); 58 return 0; 59 } 60 61 inline int read() { 62 static int x; 63 static char ch; 64 x = 0, ch = getchar(); 65 while (ch < '0' || '9' < ch) 66 ch = getchar(); 67 while ('0' <= ch && ch <= '9') { 68 x = x * 10 + ch - '0'; 69 ch = getchar(); 70 } 71 return x; 72 }