1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
2017-09-09 08:55
363 查看
题目链接
题目大意:n个数,分成若干段,若该段中有k个不同的数,定义该段的费用k*k,求最小费用
题解:只会n^2……f(i)=min{f(j)+sum(j+1,i)2}(0≤j<i)
观察到对于一个区间,其答案上界为len,也就是说区间内最多len−−−√种不同的数
那么枚举颜色段数
动态维护最优转移点pos[j]表示以i为右端点,区间内共j种数字的最远左端点−1(为了转移方便)
f(i)=min{f(pos(j))+j∗j}(0≤j≤n√)
然后维护pos(j)就可以O(nn√)了
记录pre[i]为i位置的数上次出现的位置,cnt[j]为[pos[j]+1,i]中不同数字个数
跪啊
我的收获:寻找答案上界奇妙优化,数学大法
正常做法
实现的时候直接用双向链表删掉相同的位置,只保留最后一个
题目大意:n个数,分成若干段,若该段中有k个不同的数,定义该段的费用k*k,求最小费用
题解:只会n^2……f(i)=min{f(j)+sum(j+1,i)2}(0≤j<i)
观察到对于一个区间,其答案上界为len,也就是说区间内最多len−−−√种不同的数
那么枚举颜色段数
动态维护最优转移点pos[j]表示以i为右端点,区间内共j种数字的最远左端点−1(为了转移方便)
f(i)=min{f(pos(j))+j∗j}(0≤j≤n√)
然后维护pos(j)就可以O(nn√)了
记录pre[i]为i位置的数上次出现的位置,cnt[j]为[pos[j]+1,i]中不同数字个数
跪啊
我的收获:寻找答案上界奇妙优化,数学大法
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; #define M 50005 int n,m,a[M]; int pos[M],cnt[M],f[M]; int pre[M],nxt[M],last[M]; void Dp() { memset(f,0x3f,sizeof(f));f[0]=0; for(int i=1;i<=n;i++) { for(int j=1;j*j<=n;j++) if(pre[i]<=pos[j]) ++cnt[j];//a[i]上次位置不在[pos[j]+1,i]中,加入a[i] for(int j=1;j*j<=n;j++) if(cnt[j]>j)//超出范围 { pos[j]++;//移动左端点pos[j]+1,暴力移动pos(j),直到完全删掉1个数字,意会一下 while(nxt[pos[j]]<=i) pos[j]++;//均摊O(1) cnt[j]--; } for(int j=1;j*j<=n;j++) f[i]=min(f[i],f[pos[j]]+j*j);//转移 } } void work() { Dp(); printf("%d\n",f ); } void init() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]),pre[i]=last[a[i]],last[a[i]]=i; memset(last,0,sizeof(last)); for(int i=n;i>=1;i--) nxt[i]=last[a[i]],last[a[i]]=i; for(int i=1;i<=n;i++) if(!nxt[i]) nxt[i]=n+1;//net数组注意赋值!! } int main() { init(); work(); return 0; }
正常做法
实现的时候直接用双向链表删掉相同的位置,只保留最后一个
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; #define M 50005 int n,a[M]; int pos[M],f[M]; int pre[M],nxt[M]; void del(int x) { nxt[pre[x]]=nxt[x]; pre[nxt[x]]=pre[x]; } void Dp() { memset(f,0x3f,sizeof(f));f[0]=0; for(int i=1;i<=n;i++) { if(!pos[a[i]]) pos[a[i]]=i; else del(pos[a[i]]),pos[a[i]]=i; int cnt=0; for(int j=pre[i];j!=-1;j=pre[j]){ cnt++; f[i]=min(f[i],f[j]+cnt*cnt); if(cnt*cnt>i) break; } } } void work() { Dp(); printf("%d\n",f ); } void init() { scanf("%d%*d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) pre[i]=i-1,nxt[i]=i+1; pre[0]=-1; } int main() { init(); work(); return 0; }
相关文章推荐
- 【BZOJ】1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
- BZOJ1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
- [BZOJ1584][Usaco2009 Mar]Cleaning Up 打扫卫生(dp+数学相关优化)
- bzoj1584[Usaco2009 Mar]Cleaning Up 打扫卫生
- BZOJ_1584_[Usaco2009 Mar]Cleaning Up 打扫卫生_DP
- 【BZOJ1584】[Usaco2009 Mar]Cleaning Up 打扫卫生【DP】
- [bzoj1584] [Usaco2009 Mar]Cleaning Up 打扫卫生
- [bzoj1584] [Usaco2009 Mar]Cleaning Up 打扫卫生
- 【bzoj1584】[Usaco2009 Mar]Cleaning Up 打扫卫生 DP
- bzoj1584【Usaco2009 Mar】Cleaning Up 打扫卫生
- BZOJ1584 [Usaco2009 Mar]Cleaning Up 打扫卫生
- [bzoj1584][Usaco2009 Mar 4000 ]Cleaning Up 打扫卫生
- bzoj 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
- bzoj1584 [Usaco2009 Mar]Cleaning Up 打扫卫生 dp
- bzoj:1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
- [BZOJ1584] [Usaco2009 Mar]Cleaning Up 打扫卫生(DP)
- DP经典 BZOJ 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
- BZOJ 1584 [Usaco2009 Mar]Cleaning Up 打扫卫生 动态规划
- BZOJ1584: [Usaco2009 Mar]Cleaning Up 打扫卫生
- bzoj 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生【dp】