Making The Grade G

  原题传送门: luogu P2893 USACO08FEB

  题目大意: 给定一个长度为 N N N 的序列 A A A 让你构造一个长度也为 N N N 的序列 B B B,且 B B B 非严格单调(不限制单增或单减),且要最小化 T = ∑ i = 1 N ∣ A i − B i ∣ T = \sum\limits_{i=1}^N \mid A_i - B_i \mid T=i=1∑N​∣Ai​−Bi​∣。

  因为这里分成两种情况,一种 B B B 是非严格单增的,另一种 B B B 是非严格单减的,所以我们考虑分别对这两种情况进行求解,最后再去一个最小值就好了。下面我们就以 B B B 是非严格单增来举例子(非严格单减同理)。

  在分析的过程中,我们发现一个神奇的现象,在满足最小化 T T T 的前提下,一定存在一种构造 B B B 的方案,使得 B B B 中的所有数值都在 A A A 中出现过。首先,当 N = 1 N = 1 N=1 的时候这个命题显然成立(最小化 T T T 之间让 B 1 = A 1 B_1 = A_1 B1​=A1​ 就好了)。之后我们考虑先假设这个命题对 N = k − 1 N = k-1 N=k−1 成立,如果能推出这个命对 N = k N = k N=k 成立,在运用数学归纳法,就能证明这个命题对所有 N N N 都成立了。

  现在设命题对 N = k − 1 N = k-1 N=k−1 时成立,且此时构造出来的序列是 B 1 ∼ B k − 1 B_1 \sim B_{k-1} B1​∼Bk−1​。然后我们来分类讨论 B k − 1 B_{k-1} Bk−1​ 和 A k A_k Ak​ 的大小情况:

  1. 如果 B k − 1 ≤ A k B_{k-1} \leq A_k Bk−1​≤Ak​,则令 B k = A k B_k = A_k Bk​=Ak​ 则我们就把 k k k 这里消成了 0,而且还满足单增。并且前面已经构造出最小的了,所以现在肯定也是最小的,此时命题成立。
  2. 当 B k − 1 > A k B_{k-1} > A_k Bk−1​>Ak​ 的时候还要分成两种情况,第一种情况是直接令 B k = B k − 1 B_k = B_{k-1} Bk​=Bk−1​ 命题成立。
      第二种当这样直接构造不成立的时候就要考虑其他的构造方式了。因为直接令 B k = B k − 1 B_{k} = B_{k-1} Bk​=Bk−1​ 不行了,所以我们考虑下调 B B B 数列前面的数,因为要向下调整,所以我们前面构造好的数也要向下一起调整。
      所以我们发现,我们一定能够找到一个 j j j 然后重新令 B j , B j + 1 , ⋯ B k B_{j}, B_{j+1}, \cdots B_{k} Bj​,Bj+1​,⋯Bk​ 都等于一个新的值 x x x,使得原命题成立。但是为什么要统一下调到 x x x 呢,难道不存在一种可能使得前面的数下调到比 x x x 还小使得整个数列的 T T T 更优吗?显然是不存在的,因为如果可以让前面的更小来满足更优那么这个数就不会在 [ j , k ] [j, k] [j,k] 这一段里,它会在之前构造 k − 1 k-1 k−1 的长度的时候就被调成更小的而满足最优。
      这个时候问题就变成了找到一个数 x x x 证明当 T ′ = ∑ i = j k ∣ x − A i ∣ T' = \sum\limits_{i=j}^k \mid x - A_i \mid T′=i=j∑k​∣x−Ai​∣ 时 x x x 一定在 A A A 里面出现过。而对于这个式子: T ′ = ∑ i = j k ∣ x − A i ∣ T' = \sum\limits_{i=j}^k \mid x - A_i \mid T′=i=j∑k​∣x−Ai​∣,其实就是一个中位数问题。设 m i d mid mid 是 A [ j ∼ k ] A[j\sim k] A[j∼k] 的中位数,如果 m i d ≥ B j − 1 mid \geq B_{j-1} mid≥Bj−1​,让 x = m i d x = mid x=mid 就能最小化 T ′ T' T′。当 m i d < B j − 1 mid < B_{j-1} mid<Bj−1​ 的时候我们就让 x = B j − 1 x = B_{j-1} x=Bj−1​ 就能保证最优且单调。而且 m i d mid mid 和 B j − 1 B_{j-1} Bj−1​ 都是 A A A 中的数值。所以原命题成立。

  我们上面已经证明了这个神奇的命题,那下面转移方程就比较容易了。我们设 F [ i ] F[i] F[i] 表示对于 A [ 1 ∼ i ] A[1\sim i] A[1∼i] 完成构造,且 A [ i ] = B [ i ] A[i] = B[i] A[i]=B[i] 的时候, T T T 的最小值。我们仿照 LIS 就能得到下面的动态转移方程:
F [ i ] = min ⁡ 0 ≤ j < i , A [ j ] ≤ A [ i ] { F [ j ] + c ( j + 1 , i − 1 ) } F[i] = \min_{0 \leq j < i, A[j] \leq A[i]}\lbrace F[j] + c(j+1, i-1) \rbrace F[i]=0≤j<i,A[j]≤A[i]min​{F[j]+c(j+1,i−1)}

  其中,我们设 c ( j + 1 , i − 1 ) c(j+1, i-1) c(j+1,i−1) 表示构造 B j + 1 , B j + 1 , ⋯ B i − 1 B_{j+1}, B_{j+1}, \cdots B_{i-1} Bj+1​,Bj+1​,⋯Bi−1​ 的最小代价。也就是构造出 B j + 1 , B j + 1 , ⋯ B i − 1 B_{j+1}, B_{j+1}, \cdots B_{i-1} Bj+1​,Bj+1​,⋯Bi−1​,且满足 A j ≤ B j + 1 ≤ B j + 1 ≤ ⋯ ≤ B i − 1 ≤ A i A_j \leq B_{j+1} \leq B_{j+1} \leq \cdots \leq B_{i-1} \leq A_i Aj​≤Bj+1​≤Bj+1​≤⋯≤Bi−1​≤Ai​ 的时候 ∑ k = j + 1 i − 1 ∣ A k − B k ∣ \sum\limits_{k=j+1}^{i-1}\mid A_k - B_k \mid k=j+1∑i−1​∣Ak​−Bk​∣ 的最小值。

  现在我们就要想办法求解出 c ( j + 1 , i − 1 ) c(j+1, i-1) c(j+1,i−1) 等于多少了。根据我们上面的神奇的命题, B B B 数列一定是由一段一段的 A A A 数列里面的值组成的,又因为 i i i 处刚好 A [ i ] = B [ i ] A[i] = B[i] A[i]=B[i] 且 j j j 处也满足 A [ j ] = B [ j ] A[j] = B[j] A[j]=B[j],所以我们要构造的中间的一坨东西就是前面一部分是 A [ j ] A[j] A[j],后面一部分是 A [ i ] A[i] A[i] 的一个序列,然后我们就用一个 k k k 来枚举分界点就好了。这样的算法的时间复杂度就是 O ( n 3 ) O(n^3) O(n3),显然过不了。

  然后我们考虑优化一下,一个状态的转移不行,我们就多加一个状态,我们直接把上一次构造的 B B B 序列的最后一个值也加在状态里面,也就是记 F [ i , j ] F[i, j] F[i,j] 表示完成对 A [ 1 ∼ i ] A[1\sim i] A[1∼i] 的构造,且构造出来的 B B B 中 B [ i ] = j B[i] = j B[i]=j 时 T T T 的最小值。那么我们就有:
F [ i , j ] = min ⁡ 0 ≤ k < j { F [ i − 1 , k ] + ∣ A [ i ] − j ∣ } F[i, j] = \min_{0 \leq k < j} \lbrace F[i-1, k] + \mid A[i] - j \mid \rbrace F[i,j]=0≤k<jmin​{F[i−1,k]+∣A[i]−j∣}

  然后我们可以对 A A A 进行离散化,把状态的第二维降到 O ( n ) O(n) O(n)。然而状态转移还是 O ( n ) O(n) O(n) 的,所以整个的复杂度也还是 O ( n 3 ) O(n^3) O(n3) 的。但是我们可以继续优化,我们记 S ( j ) S(j) S(j) 表示满足转移条件 0 ≤ k < j 0 \leq k < j 0≤k<j 的所有 k k k 的集合。我们发现,在每一次枚举 j j j 的时候这个决策集合只增不减,所以在找 k k k 的时候我们就不用每次都枚举 k k k,直接用 j j j 来代表 k k k 就可以了,这样我们就可以做到 O ( 1 ) O(1) O(1) 的转移。

#include<bits/stdc++.h>
using namespace std;
#define MAXN 2020
#define endl '\n'int a[MAXN] = { 0 };
int b[MAXN] = { 0 };
int n = 0; int m = 0;int ans = 0;
int f[MAXN][MAXN] = { 0 };
void dp(){for(int i = 1; i <= n; i++){int minx = f[i-1][1];for(int j = 1; j <= n; j++){minx = min(minx, f[i-1][j]);f[i][j] = minx + abs(b[j] - a[i]);}}
}int main(){scanf("%d", &n);for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];sort(b+1, b+n+1); m = unique(b+1, b+n+1) - b - 1;dp(); ans = f[n][1];for(int i = 2; i <= m; i++) ans = min(ans, f[n][i]);reverse(a+1, a+n+1); dp();for(int i = 1; i <= m; i++) ans = min(ans, f[n][i]);cout << ans << endl;return 0;
}

Making The Grade G相关推荐

  1. [USACO08FEB]Making the Grade G 和 CF714E

    Making the Grade G 题意: 一个农夫需要修路,每一段路的海拔为 A i A_i Ai​,修改后的海拔为 B i B_i Bi​,花费为 ∣ A i − B i ∣ |A_i-B_i| ...

  2. 16_python_面向对象

    一.面向对象和面向过程的区别 1.面向对象:一切以对象为中心.有相同属性和动作的结合体叫做对 优点:易维护.易复用.易扩展,由于面向对象有封装.继承.多态性的特性,可以设计出低耦合的系统,使系统 更加 ...

  3. 刻意练习:Python基础 -- Task10. 类与对象

    背景 我们准备利用17天时间,将 "Python基础的刻意练习" 分为如下任务: Task01:变量.运算符与数据类型(1day) Task02:条件与循环(1day) Task0 ...

  4. Python基础,面向对象

    几个名词知识: 类(Class): 用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例. 类变量:类变量在整个实例化的对象中是公用的.类变量定义在类中 ...

  5. Python-面向对象 (二 继承)

    一 继承   基类定义例如以下: class people:     #define attribute     name = ''     age  = 0     #define private ...

  6. python 类的继承,类中的函数调用以及类输入数组

    第一部分,类的继承 先给出一个例子: class People(): #定义类,要大写,python 2中要在括号里加如object这个单词def __init__(self,n,a,w): #定义一 ...

  7. javaweb学习总结三(枚举)

    一:枚举的概念 定义特定的数据,尤其像一些状态位. 二:定义枚举类 1:定义枚举,其中Grade枚举可以看做类,A.B.C.D.E可以看做对象,因为它定义了有参数的构造方法,所以 对象后面必须带参数. ...

  8. C++this指针操作

    在这里总结一下this 指针的相关知识点. 首先,我们都知道类的成员函数可以访问类的数据(限定符只是限定于类外的一些操作,类内的一切对于成员函数来说都是透明的),那么成员函数如何知道哪个对象的数据成员 ...

  9. 两只小熊队高级软件工程第七次作业敏捷冲刺7

    团队的作业:学生信息管理系统 队员学号: 周菲(队长) 201810812007 孔繁燕   201810812001 Alpha敏捷冲刺: 1. 站立式会议照片: 2.每个人的工作: 周菲: 今天已 ...

最新文章

  1. 南洋理工大学科学家研发组装机器人,可以帮助用户组装椅子
  2. [转]七大.NET开源框架
  3. Dubbo-go 源码笔记(一)Server 端开启服务过程
  4. 简单拨号器(Android)
  5. 解决windows下Error:node with name rabbit already running on “XXX” 和管理页面打不开问题
  6. Android模拟器读取GPS串口模拟器GPS数据
  7. java学生宿舍管理系统,来了就点个赞再走呗,即将毕业的兄弟有福了
  8. 【JVM · 调优】监控及诊断工具
  9. wps表格宏被禁用如何解禁_wps excel宏被禁用如何启用 - 卡饭网
  10. Python3爬虫 爬句子迷
  11. 生物素-磺酸-NHS 酯,119616-38-5,Biotin-Sulfo-NHS ester
  12. 什么牌子的蓝牙耳机性价比高质量好?高性价比降噪蓝牙耳机推荐
  13. WSTMart二次开发目录说明
  14. 支付宝授权登录免费源码奉献
  15. 0315 财经爬虫实战
  16. Java学习打卡第七天——[再谈Collection之Set,TreeSet,泛型Generic的简介和使用]
  17. 码住!人工智能怎么影响教育?听这场直播就够了!
  18. (Modern Family S01E01) Part 7  PhilClair  Dylan初访Dunphy家
  19. 【调剂】211中国矿业大学(徐州)2020年硕士研究生拟调剂专业
  20. 汉诺塔问题(三阶梵塔问题)

热门文章

  1. 查看Mysql数据库连接IP
  2. 如何对付网络爬虫 - JavaEye和网络爬虫斗争之路
  3. 如何修好一本家谱?怎样才能符合修谱规范?2022年修谱:利用工具
  4. win7怎么跳过硬盘自检_华硕品牌机win10改win7系统教程
  5. mysql事务内_MySQL事务
  6. 基于模型的设计 | Preceyes加速全球首款眼科手术机器人的开发
  7. Latex排版——爱思唯尔模板使用
  8. 计算机丢失deferrd.dll怎么解决,RdpSaPs.dll
  9. 详解勒让德变换与共轭函数
  10. linux怎么看数据库实例,Linux/Unix平台如何查看OS上存在有哪些数据库或实例