DP经典 BZOJ 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生

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

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 419  Solved: 278

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

 1 /*因为这个题目分组是没有限制的,所以我们DP方程不能把分组作为一个状态
 2 正解:最差情况每个数位于一段,ans=n,所以若有一段区间内不同的数的数量<=sqrt(n),否则结果一定不是最优。
 3 nsqrt(n)求法:维护b[j],c[j],f[j],pre[j]数组。
 4 b[j]表示b[j]+1...i有j个不同的数的区间的最左端。
 5 那么可以知道f[i]=min{f[i],f[b[j]]+j*j};这样时间复杂度就降了下来
 6 如何维护b[j]数组,当i向后移动一位的时候,pre[a[i]]记录a[i]出现的最后一个位置是哪里?
 7 那么:i++后,pre[a[i]]<=b[j],说明b[j]+1...到i这段序列的不同数的数目就是j+1了,我们用c[j]来记录这个情况,顺便更新pre[a[i]],而且始终维护c[j]==j;
 8 那么b[j]仍然是符合题意的。
 9 维护c[j]就要从b[j]+1开始向后面删除数据,删除时判断若pre[a[t]]>t,则说明是删除了相同的数,对于最后的和谐值没有影响,所以还要删数
10 知道pre[a[t]]<=t,删除a[t],顺便更新b[j]的位置
11 */
12 #define N 40100
13 #include<iostream>
14 using namespace std;
15 #include<cstdio>
16 #include<cmath>
17 #include<cstring>
18 int f[N],b[N],c[N],pre[N],a[N];
19 int n,m;
20 void input()
21 {
22     scanf("%d%d",&n,&m);
23     for(int i=1;i<=n;++i)
24       scanf("%d",&a[i]);
25     memset(pre,-1,sizeof(pre));/*别忘了设置为-1,因为下面会与b[j]==0的初值进行比较*/
26     memset(f,127,sizeof(f));
27 }
28 void chuli()
29 {
30     int sqrtn=sqrt(n+0.5);
31     f[0]=0;/*初始化,前0个数的不和谐值为0,*/
32     for(int i=1;i<=n;++i)
33     {
34         for(int j=1;j<=sqrtn;++j)
35         {
36             if(pre[a[i]]<=b[j])
37               c[j]++;/*统计新加入的数是不是符合要求*/
38         }
39         pre[a[i]]=i;/*更新pre*/
40         for(int j=1;j<=sqrtn;++j)
41         {
42             if(c[j]>j)/*删除数,缩短序列*/
43             {
44                 int t=b[j]+1;
45                 while(pre[a[t]]>t) ++t;
46                 b[j]=t;c[j]--;
47             }
48         }
49         for(int j=1;j<=sqrtn;++j)
50           f[i]=min(f[i],f[b[j]]+j*j);/*更新f*/
51     }
52 }
53 int main()
54 {
55     input();
56     chuli();
57     cout<<f[n]<<endl;
58     return 0;
59 }
60 /*这个题目既然不以划分次数为状态,那么可以考虑,划分序列的长度*/
时间: 2024-08-02 12:23:13

DP经典 BZOJ 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生的相关文章

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

1584: [Usaco2009 Mar]Cleaning Up 打扫卫生 Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k.那总的不河蟹度就是所有段的不河蟹度的总和. Input 第一行:两个整数N,M 第2..N+1行:N个整数代表每个奶牛的编号 Output 一个整数,代表最小不河蟹度 Sampl

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

[算法]DP+数学优化 [题意]把n个1~m的数字分成k段,每段的价值为段内不同数字个数的平方,求最小总价值.n,m,ai<=40000 [题解] 参考自:WerKeyTom_FTD 令f[i]表示把前i个数分成若干段的最小价值. 转移中我们定义,从i开始往前到有j个不同的数的最小位置为b[j]. f[i]=f[b[j]-1]+j^2. 考虑最坏情况,每个数自成一段,则总价值为n. 所以当段内不同的数个数>√n时,就不可能是最优解了(此时价值>n). 所以f[i]=f[b[j]-1]+j

动态规划 BZOJ1584 [Usaco2009 Mar] Cleaning Up 打扫卫生

1584: [Usaco2009 Mar]Cleaning Up 打扫卫生 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 511  Solved: 349[Submit][Status][Discuss] Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k.

[BZOJ1584] [Usaco2009 Mar]Cleaning Up 打扫卫生(DP)

传送门 不会啊,看了好久的题解才看懂 TT 因为可以直接分成n段,所以就得到一个答案n,求解最小的答案,肯定是 <= n 的, 所以每一段中的不同数的个数都必须 <= sqrt(n),不然就不是最小的答案 那么 f[i]表示前i个数的最有解 g[i]表示从当前位置开始,有i个不同的数,最多能往前延伸到哪里 pre[i]表示上一个数为i的位置 cnt[i]表示g[i] + 1 ~ 当前位置 中的不同数的个数 所以 f[i] = min(f[i], f[g[j]] + j * j) 那么问题就是g

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 Pr

bzoj1584 9.20考试 cleaning up 打扫卫生

1584: [Usaco2009 Mar]Cleaning Up 打扫卫生 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 549  Solved: 382[Submit][Status][Discuss] Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k.

bzoj 1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害

1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害 Description Farmer John的农场里有P个牧场,有C条无向道路连接着他们,第i条道路连接着两个牧场Ai和Bi,注意可能有很多条道路连接着相同的Ai和Bi,并且Ai有可能和Bi相等.Farmer John在1号牧场里.由于地震,某些牧场被损坏,但由于信春哥,C条道路没有一条损坏.有N头奶牛,他们在不同的牧场里,于是N <= P.他们一一向Farmer John报告.第i头奶牛报告给Farm

BZOJ 3399 [Usaco2009 Mar]Sand Castle城堡(贪心)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3399 [题目大意] 将一个集合调整成另一个集合中的数,把一个数+1需要消耗x,-1需要消耗y,问最小消耗. [题解] 显然两个集合排序之后一一对应调整需要消耗的才是最少的,所以排序计算答案即可. [代码] #include <cstdio> #include <algorithm> using namespace std; const int N=25010; int

BZOJ 3407: [Usaco2009 Oct]Bessie&#39;s Weight Problem 贝茜的体重问题( dp )

01背包... ----------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define rep( i , n ) for( int i = 0 ; i < n ; i++ ) #define clr( x , c ) m