bzoj1584 打扫卫生 dp

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1584

题意:找到某种分割序列方法,使得每一段中所含数的种类平方之和最小。

考试时一时脑残连暴力$dp$都没写出来……

首先暴力dp应该都写得出来……$f[i]=min(f[j]+(cnt[j~i])^2)$

正解有个比较智障的优化……首先可以想到答案不会差过$n^2$(最差就是每一个一段),因此,我们只需要记录每段中有$1,2,3……sqrt(n)$个不同元素的情况,找到这些段开始的位置的前一个位置,记作$pos[j]$,那么,$f[i]=min(f[pos[j]]+j*j)$。

下面重点问题就变为$i$改变时如何修改$pos$数组。为方便我们再记录每种数字出现的上个位置$pre[j]$和每一段中有的数字种类$cnt[j]$。

首先,如果$pre[a[i]]<=pos[j]$,则$cnt[j]++$。

然后对于每一个$cnt[j]>j$的情况,暴力右移左端点,如果这时$pre[a[pos[j]]]==pos[j]$,$cnt[j]--$。

问题得解。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 const int maxn=40005;
 8 int a[maxn],pos[maxn],cnt[maxn],pre[maxn],n,m,f[maxn];
 9 int haha()
10 {
11     scanf("%d%d",&n,&m);
12     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
13     memset(f,0x3f,sizeof(f));f[0]=0;int num=(int)sqrt(n);
14     for(int i=1;i<=n;i++)
15     {
16         for(int j=1;j<=num;j++)
17             if(pre[a[i]]<=pos[j])cnt[j]++;
18         pre[a[i]]=i;
19         for(int j=1;j<=num;j++)
20             while(cnt[j]>j)
21             {
22                 pos[j]++;
23                 if(pre[a[pos[j]]]==pos[j])cnt[j]--;
24             }
25         for(int j=1;j<=num;j++)f[i]=min(f[i],f[pos[j]]+j*j);
26     }
27     printf("%d\n",f[n]);
28 }
29 int sb=haha();
30 int main(){;}

bzoj1584

时间: 2024-08-24 18:20:46

bzoj1584 打扫卫生 dp的相关文章

动态规划 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.

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

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

「10.12」木板(数学)&#183;打扫卫生(神仙DP)

A. 木板 一个很简单的数学题,简单推一下就好,路丽姐姐教你学数学. 将式子化出我们发现只需求出$i\times i/n$的个数 那么我们将$n$质因数分解,可知因子个数 为了整除$n$,令$i==\sqrt{n\times k} $,我们需要让$k$含有$n$中奇数个数的因子 然后同时还可以有其他的平方因子,直接爆求即可. 思路积累: 1.对于求$i\times i/n$可以从$n$的因子上下手 B. 打扫卫生 一个$DP$的大神题,考场被各种剪枝cao过 $ \%\%\%\%\%kx,Dua

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 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

10.12 csp-s模拟测试70 木板+打扫卫生+骆驼

T1 木板 求\sqrt{n}-n间有多少个数的平方是n的倍数 通过打表可以发现(我没带脑子我看不出来),符合条件的数构成一个等差数列,公差为首项 而首项就是将n质因数分解后每个质因数出现次数除二,向上取整,这个数一定是大于\sqrt{n}的最小的符合条件的数 \sqrt{n}将n分解质因数后求出首项,(n-1)/首项就是小于n里有几个,即答案 积累:papa大神教我,打表之前先猜规律,用小点看看猜的对不对,然后再用大点验证,想不出来的数学题就打打表,找找规律 T2 打扫卫生 首先肯定是dp 考

[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

程序员如何打扫卫生并向老婆汇报

如果有一天, 你老婆(或老妈),周末要出门, 让你打扫一下家里. 这是一个难题.但是,难不倒优秀的程序员, 让我们用geek的方法解决这个问题. 1. 为了证明你有打扫过, 有对比才有差异, 我们先给客厅照个相, 例如你客厅是这样的: (打扫前) 恩,很漂亮的客厅, 虽然程序员家应该没有这么干净漂亮, 不过请不要在意这些细节. 2. 接下来是最关键的一步:打开美图秀秀. 好了, 现在在美图秀秀中,你可以去掉照片中的污垢, 还可以加上你喜欢的效果(小星星什么的).但是注意效果别加得太过火,这样会让