BZOJ1584 [Usaco2009 Mar]Cleaning Up 打扫卫生

令$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 }
View Code

 

转载于:https://www.cnblogs.com/rausen/p/4458654.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值