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. C#Object与XML文件或二进制文件之间的转化

    Object To Xml 文件 public static bool Serializer<T>(object obj, string path) { FileStream xmlfil ...

  2. Linux上 安装Sorl4.7 中间件用tomcat

    最近需要用到solr,公司内部搭建了一个solr测试环境. 版本:solr4.7.2 ,tomcat 7.0.55 jdk:1.7_051 解压 solr 和tomcat  这里就不详说. 1.启动t ...

  3. Spring Boot + kkFileView-2.1.2 实现文档在线预览

    1. 下载kkFileview:https://gitee.com/kekingcn/file-online-preview/releases 2. 启动服务 进入 bin 目录,双击 startup ...

  4. sklearn算法中的顶层设计

    sklearn监督学习的各个模块 neighbors近邻算法,svm支持向量机,kernal_ridge核岭回归,discriminant_analysis判别分析,linear_model广义线性模 ...

  5. POJ 2763 /// 基于边权的树链剖分

    题目大意: 给定n个结点,有n-1条无向边,给定每条边的边权 两种操作,第一种:求任意两点之间路径的权值和,第二种:修改树上一点的权值. 因为是一棵树,可以直接把 u点和v点间(假设u为父节点,v为子 ...

  6. Web UI 设计(网页设计)命名规范

    Web UI 设计命名规范 一.网站设计及基本框架结构: 1.    Container“container“ 就是将页面中的所有元素包在一起的部分,这部分还可以命名为: “wrapper“, “wr ...

  7. capserjs-prototype(下)

    scrollTo() 具体样式: scrollTo(Number x, Number y) New in version 1.1-beta3. Scrolls current document to ...

  8. ES6 学习 -- Class继承

    (1)如何继承Class可以通过extends关键字实现继承,如下:class Father { } class Child extends Father { }// 这里子类Child继承父类Fat ...

  9. Django ORM 之 单表、多表查询

    返回ORM目录 Django ORM Django ORM 之一 内容目录: 一.单表查询 二.多表查询 0.准备工作 一些说明: - 表myapp_person的名称是自动生成的,如果你要自定义表名 ...

  10. lombok使用手册

    lombok使用手册: 1.安装插件 1.1.idel: 1.2.使用lombok还需要引用相关jar包 参考网址:https://projectlombok.org/features/all 2.注 ...