[bzoj1584] [Usaco2009 Mar]Cleaning Up 打扫卫生
来源:互联网 发布:牵黄擎苍岂可得乎 编辑:程序博客网 时间:2024/04/25 14:54
[bzoj1584] [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
一个整数,代表最小不河蟹度.
这题好神啊!
首先,我们不难想到
设f[i]为前i个数的答案,那么最终答案就是f[n].
考虑到我们在状态转移时对于每一个f[i]都要从前往后扫一遍取最大值,十分耗时间,那么我们有什么好的办法能在更快的时间内得到f[i]的答案呢?
有的.
我们维护一个数组pos[j]表示一个位置,这个位置有什么性质呢?它记录的是从pos[j]+1到当前的i位置有j个不同的数.那么就有f[i]=max(f[pos[j]]+j*j)了.
然而pos[j]中j上界未得到确定,所以接下来我们考虑枚举的j的上界.我们目前知道的答案的最大值是n,即把每个数单独分成一组所得到的答案.那么我们对于其它答案大于n的区间分配方案就要舍去了.考虑到如果一个区间有超过
结合pos[j]的性质,那么我们枚举的j就只要到
由于i是改变的,那么显然pos[j]不是一个定值,它可能时刻都在变化.考虑到pos[j]的性质与该位置到i位置中不同的数的个数有关,我们需要设立一个数组cnt[j]表示从pos[j]+1到i中不同的数的个数.对于新加入的一个数A[i],我们也需要记录它上次出现的位置pre[A[i]],所以如果pre[A[i]]小于或等于pos[j],那么说明它在pos[j]+1到i中没有出现过,那么cnt[j]++.于是我们维护了cnt数组的性质.当然,这样一番过后,可能cnt[j]就会大于j了(准确的说是等于j+1),那么就与pos[j]的性质相违背,我们就要调整pos[j]的位置了.
其实调整它也好办,就是减去一类数,那么我们在pos[j]+1到i的区间中找到第一个它的前驱pre出现在它左边的数,那么就说明从这个数的位置+1到i都没有这个数了,由于是第一个,那么它之前的数还会在这个区间中出现.所以cnt[j]–,pos[j]就更新成为我们找到的这个数的位置.pos数组就能得到维护了.
我的题解估计是我看过的所有题解里面写的最详细的了.时间复杂度
贴上代码
#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>using namespace std;static const int maxm=1e6+10;int A[maxm],pre[maxm],f[maxm],pos[maxm],cnt[maxm];int n,m;int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&A[i]); memset(pre,-1,sizeof pre);memset(f,127/3,sizeof f); int block=(int)sqrt(n); f[0]=0; for(int i=1;i<=n;i++){ for(int j=1;j<=block;j++) if(pre[A[i]]<=pos[j])cnt[j]++; pre[A[i]]=i; for(int j=1;j<=block;j++){ if(cnt[j]>j){ int now=pos[j]+1; while(pre[A[now]]>now)now++; pos[j]=now;cnt[j]--; } } for(int j=1;j<=block;j++) f[i]=min(f[i],f[pos[j]]+j*j); } printf("%d\n",f[n]); return 0;}
传送门(bzoj权限题,提供另一个OJ的网站)
- bzoj1584【Usaco2009 Mar】Cleaning Up 打扫卫生
- [bzoj1584] [Usaco2009 Mar]Cleaning Up 打扫卫生
- 【BZOJ1584】[Usaco2009 Mar]Cleaning Up 打扫卫生【DP】
- bzoj1584 [Usaco2009 Mar]Cleaning Up 打扫卫生 dp
- 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
- [BZOJ1584][Usaco2009 Mar]Cleaning Up 打扫卫生(dp+数学相关优化)
- BZOJ 1584 [Usaco2009 Mar]Cleaning Up 打扫卫生 动态规划
- DP Cleaning Up 打扫卫生
- [Usaco2009 Mar]Cleaning Up
- [bzoj1584]打扫卫生
- bzoj 1584 Cleaning Up 打扫卫生 dp
- bzoj1584 [ Usaco2009 Mar ] --DP
- BZOJ 1584 [Usaco2009 Mar] Cleaning Up
- BZOJ1584 USACO 2009 Mar Gold 2.Cleaning Up
- bzoj3401[Usaco2009 Mar]Look Up 仰望
- [BZOJ3401] [Usaco2009 Mar]Look Up 仰望
- BZOJ 3401: [Usaco2009 Mar]Look Up 仰望
- bzoj 3401: [Usaco2009 Mar]Look Up 仰望
- bzoj 4545: DQS的trie (后缀自动机+LCT)
- jQuery分页插件
- MATLAB中的simulink 的示波器编辑
- 课堂笔记_ 颜色模型、Phong光照模型
- RequestMapping的相关知识讲解
- [bzoj1584] [Usaco2009 Mar]Cleaning Up 打扫卫生
- java下载中文文件名乱码问题
- Rikka with Graph HDU
- Oracle使用需要注意的内容
- Java堆结构PriorityQueue完全解析
- 模态框中的data-属性
- SpringMVC
- 用本机电脑搭建网站(域名、DNS解析)
- SQL数据库常用命令