bzoj1584 9.20考试 cleaning up 打扫卫生

1584: [Usaco2009 Mar]Cleaning Up 打扫卫生

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 549  Solved: 382
[Submit][Status][Discuss]

Description

有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000。现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k。那总的不河蟹度就是所有段的不河蟹度的总和。

Input

第一行:两个整数N,M

第2..N+1行:N个整数代表每个奶牛的编号

Output

一个整数,代表最小不河蟹度

Sample Input

13 4
1
2
1
3
2
2
3
4
3
4
3
1
4

Sample Output

11

HINT

   这道题当时是被m坑了所以先提前声明一下m没有任何卵用,没有任何卵用,没有任何卵用!又被丝薄出题人坑了。

   当时以为m是限制的次数,然后就开始手推了十多分钟的样例,各种搞都没用,然后就快崩溃了,TMm到底是什么呀?于是万念俱灰的我打了一个大爆搜,然后惊喜的发现m真的不是次数,然后就等着这个暴力拿分了,连正解都忘了去想,天知道O(n^2)能拿70分,直接跪了,疼啊。

  正解个人表示根本看不懂,于是乎向指针恒学了一下暴力。

  同n^2的暴力一样,原理也是一样,暴力枚举,但我们可以观察到对于一个点,他的最优解一定小于等于i所以我们只要枚举到不同的点有sqrt(i)就可以直接退出了,省了不少时间,其次也是最重要的一点,别用min,用if比较。

 1 #pragma GCC optimze("O3")
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<queue>
 7 #include<algorithm>
 8 #include<cmath>
 9 #include<map>
10 #include<vector>
11 #define N 40005
12 using namespace std;
13 int n,m,a[N],f[N],pre[N];
14 bool fw[N];
15 int main()
16 {
17     scanf("%d%d",&n,&m);
18     for(int i=1;i<=n;i++)
19         scanf("%d",&a[i]);
20     memset(f,0xf,sizeof(f));
21     f[0]=0;
22     memset(pre,-1,sizeof(pre));
23     for(int i=1;i<=n;i++)
24     {
25         f[i]=i;
26         int js=0;
27         memset(fw,0,sizeof(fw));
28         for(int j=i;j>=0;j--)
29         {
30             if(!fw[a[j]])js++,fw[a[j]]=1;
31             if(js*js>=i)break;
32             if(f[i]>f[j-1]+js*js)
33                 f[i]=f[j-1]+js*js;
34         }
35         pre[a[i]]=i;
36     }
37     printf("%d\n",f[n]);
38     return 0;
39 }
View Code
 
posted @ 2017-09-21 19:01  Hzoi_joker  阅读(223)  评论(0编辑  收藏  举报