Making the Grade

给定长度为n的序列\(\{a_i\}\),求构造长度为n的递增序列\(\{b_i\}\),求\(\sum_{i=1}^n|a_i-b_i|\)最小值,\(1 ≤ N ≤ 2,000\)。

首先空间与时间不支持你表现\(b_i\)填什么,于是猜测\(b_i\)必然填的为\(a_i\)里的数。


证明:

显然填到第1个数满足条件,

假设前i-1个数满足条件,且为最优解。

考虑现在填到第i个数,如果\(a_i\geq b_{i-1}\),我们可以令\(b_i=a_i\)。

而如果\(a_i<b_{i-1}\),要么是\(b_i=b_{i-1}\)更优,要么得把\(b_i\)下调到x,同理前面的数也要下调,而此时必然有一段数\(b_i\)是等于x,因为如果还可以下调达到更优,之前就可以这么做了,而这一段达到最优可以是这一段对应的\(a_i\)的中位数,所以无论如何,都满足题意,故成立。


法一:

考虑到\(b_i\)中含有\(a_i\)的段性,故设\(f_i\)表示考虑到\(b_i\),且\(b_i=a_i\)的所求最小值,设\(cost(j+1,i-1)\)表示i,j间填左边填一段\(a_j\),右边填一段\(a_i\)的最小值,于是我们有

\[f_i=\min_{j=1,a_j<a_i}^{i-1}(f_j+cost(j+1,i-1))
\]

边界:\(f_0=0\)其余无限大

答案:\(\min_{i=1}^n(f_i+\sum_{j=i+1}^n|a_j-a_i|)\)

至于cost如何求,你只要维护分别维护只填\(a_i\)或者\(a_j\)前缀和,枚举中间点转移即可,最终时间复杂度\(O(n^3)\)。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
#define intmax 0x7fffffff
using namespace std;
int A[2001],dp[2001],sl[2001],
sr[2001];
il void read(int&);
template<class free>il free Abs(free);
template<class free>il free Min(free,free);
int main(){
int n,i,j,k,l,ans(intmax);
memset(dp,66,sizeof(dp));
read(n),dp[1]=0;for(i=1;i<=n;++i){
read(A[i]);
for(j=1;j<i;++j){
if(A[j]>A[i])continue;
sl[j]=sr[j]=0,l=intmax;
for(k=j+1;k<i;++k)sl[k]=sl[k-1]+Abs(A[k]-A[j]);
for(k=j+1;k<i;++k)sr[k]=sr[k-1]+Abs(A[k]-A[i]);
for(k=j;k<i;++k)
l=Min(l,sl[k]-sl[j]+sr[i-1]-sr[k]);
dp[i]=Min(dp[i],dp[j]+l);
}
}
for(i=1;i<=n;++i){
j&=0;
for(k=i+1;k<=n;++k)
j+=Abs(A[k]-A[i]);
ans=Min(ans,j+dp[i]);
}printf("%d",ans);
return 0;
}
template<class free>
il free Min(free a,free b){
return a<b?a:b;
}
template<class free>
il free Abs(free x){
return x<0?-x:x;
}
il void read(int &x){
x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

法二:

最直接的感觉是要想维护递增,我必然要表现出这里填什么,预处理\(c_i\)为\(a_i\)从小到大的数组,于是设\(f[i][j]\)表示处理到\(b_i\),这里令\(b_i=c_j\)的最小值,于是我们有

\[f[i][j]=\min_{k=1}^{j}(f[i-1][k])+|a_j-a_i|
\]

根据策略集合,显然这里可以维护前缀小,于是可以优化到\(O(n^2)\)。

参考代码

#include <functional>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
#define intmax 0x7fffffff
using namespace std;
int A[2001],B[2001],
dp[2001][2001],opt[2001];
il void read(int&);
template<class free>
il free Abs(free);
template<class free>
il free Min(free,free);
int main(){
int n,i,j;read(n);
for(i=1;i<=n;++i)read(A[i]),B[i]=A[i];
sort(B+1,B+n+1);
for(i=1;i<=n;++i){
for(j=1;j<=n;++j)
dp[i][j]=Abs(A[i]-B[j])+opt[j];
opt[1]=dp[i][1];
for(j=2;j<=n;++j)opt[j]=Min(opt[j-1],dp[i][j]);
}int ans(intmax);
for(i=1;i<=n;++i)ans=Min(ans,dp[n][i]);
sort(B+1,B+n+1,greater<int>());
for(i=1;i<=n;++i){
for(j=1;j<=n;++j)
dp[i][j]=Abs(A[i]-B[j])+opt[j];
opt[1]=dp[i][1];
for(j=2;j<=n;++j)opt[j]=Min(opt[j-1],dp[i][j]);
}for(i=1;i<=n;++i)ans=Min(ans,dp[n][i]);
printf("%d",ans);
return 0;
}
template<class free>
il free Min(free a,free b){
return a<b?a:b;
}
template<class free>
il free Abs(free x){
return x<0?-x:x;
}
il void read(int &x){
x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

法三:

注意到绝对值解的移动性,故可以维护一个大根堆,如果加进去的数比大于等于堆顶,不管,如果小的话,就把这个数两次加进堆,ans累加堆顶-该数,再弹掉堆顶。

证明先放一放。

参考代码:

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <functional>
#define il inline
#define ri register
using namespace std;
priority_queue<int,vector<int>,less<int> >s;
priority_queue<int,vector<int>,greater<int> >b;
il void read(int&);
int main(){
int n,i,a;read(n);
int ans1(0),ans2(0);
read(a),s.push(a),b.push(a);
for(i=2;i<=n;++i){
read(a),s.push(a),b.push(a);
if(a<s.top())ans1+=s.top()-a,s.pop(),s.push(a);
if(a>b.top())ans2+=a-b.top(),b.pop(),b.push(a);
}printf("%d",ans1>ans2?ans2:ans1);
return 0;
}
il void read(int &x){
x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

于是我们可以得到结论,递推随着状态优化,又可以转移时优化,但贪心显然排除了太多无用的状态,故是最好的优化方式。

Making the Grade的更多相关文章

  1. kaungbin_DP S (POJ 3666) Making the Grade

    Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...

  2. POJ 3666 Making the Grade

    Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more tha ...

  3. CF719C. Efim and Strange Grade[DP]

    C. Efim and Strange Grade time limit per test 1 second memory limit per test 256 megabytes input sta ...

  4. POJ3666Making the Grade[DP 离散化 LIS相关]

    Making the Grade Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6445   Accepted: 2994 ...

  5. [CareerCup] 15.7 Student Grade 学生成绩

    15.7 Imagine a simple database storing information for students' grades. Design what this database m ...

  6. 英语语法 It all started the summer before second grade when our moving van pulled into her neighborhood

    It all started the summer before second grade when our moving van pulled into herneighborhood It all ...

  7. FPGA speed grade

    Altera的-6.-7.-8速度等级逆向排序,Xilinx速度等级正向排序. 不很严密地说,“序号越低,速度等级越高”这是Altera FPGA的排序方法, “序号越高,速度等级也越高”这是Xili ...

  8. HDU 5038 Grade(分级)

    Description 题目描述 Ted is a employee of Always Cook Mushroom (ACM). His boss Matt gives him a pack of ...

  9. hdu---(5038)Grade(胡搞)

    Grade Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Sub ...

  10. A-Making the Grade(POJ 3666)

    Making the Grade Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4656   Accepted: 2206 ...

随机推荐

  1. Greenplum(PostgreSql)函数实现批量删除表

    项目做库迁移,前期需要经常调整表结构语句,涉及多次的批量drop,本着偷懒精神写了这个函数.鉴于本函数在生产环境有巨大风险,建议测试完毕后立即删除. 主要步骤很简单:1)从pg_tables查询得到相 ...

  2. 直接用编译器按ctrl+F5运行和双击运行结果不一样

    是因为进程权限的问题,需要添加下面的代码: BOOL EnableDebugPrivilege() { HANDLE hToken; BOOL fOk=FALSE; if(OpenProcessTok ...

  3. day 87 DjangoRestFramework学习一之restful规范、APIview、解析器组件、Postman等

    DjangoRestFramework学习一之restful规范.APIview.解析器组件.Postman等   本节目录 一 预备知识 二 restful规范 三 DRF的APIView和解析器组 ...

  4. cv2.imwrite()指定图片存储路径

    cv2.imwrite("./data/photo_{}.jpg".format(i), photo)

  5. licecap图片区域问题

    之前一直好用的licecap最近突然没法用了,结果发现是屏幕分辨率的文本大小的问题,因为选了特大的.发现制作成的gif图片的区域有问题.后来改回中等的,就可以了.

  6. Spring Cloud Feign设计原理

    什么是Feign? Feign 的英文表意为“假装,伪装,变形”, 是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直 ...

  7. python学习5—一些关于基本数据结构的练习题

    python学习5—一些关于基本数据结构的练习题 # 1. use _ to connect entries in a list # if there are no numbers in list l ...

  8. 新工具Scapy

    新工具 Scapy 1.环境: 命令: pip install scapy 启动终端: 看这花里胡哨的界面那就成功啦! 注意上图中的INFO信息,如果没有安装可选包,部分功能不可用,在需要的时候单独安 ...

  9. 如何通过SVN管理好代码

    来自:http://blog.csdn.net/baronyang/article/details/6942434 ------------------------------------------ ...

  10. MapReduce1.0的缺陷