Making The Grade G
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 的大小情况:
- 如果 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,而且还满足单增。并且前面已经构造出最小的了,所以现在肯定也是最小的,此时命题成立。
- 当 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相关推荐
- [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| ...
- 16_python_面向对象
一.面向对象和面向过程的区别 1.面向对象:一切以对象为中心.有相同属性和动作的结合体叫做对 优点:易维护.易复用.易扩展,由于面向对象有封装.继承.多态性的特性,可以设计出低耦合的系统,使系统 更加 ...
- 刻意练习:Python基础 -- Task10. 类与对象
背景 我们准备利用17天时间,将 "Python基础的刻意练习" 分为如下任务: Task01:变量.运算符与数据类型(1day) Task02:条件与循环(1day) Task0 ...
- Python基础,面向对象
几个名词知识: 类(Class): 用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例. 类变量:类变量在整个实例化的对象中是公用的.类变量定义在类中 ...
- Python-面向对象 (二 继承)
一 继承 基类定义例如以下: class people: #define attribute name = '' age = 0 #define private ...
- python 类的继承,类中的函数调用以及类输入数组
第一部分,类的继承 先给出一个例子: class People(): #定义类,要大写,python 2中要在括号里加如object这个单词def __init__(self,n,a,w): #定义一 ...
- javaweb学习总结三(枚举)
一:枚举的概念 定义特定的数据,尤其像一些状态位. 二:定义枚举类 1:定义枚举,其中Grade枚举可以看做类,A.B.C.D.E可以看做对象,因为它定义了有参数的构造方法,所以 对象后面必须带参数. ...
- C++this指针操作
在这里总结一下this 指针的相关知识点. 首先,我们都知道类的成员函数可以访问类的数据(限定符只是限定于类外的一些操作,类内的一切对于成员函数来说都是透明的),那么成员函数如何知道哪个对象的数据成员 ...
- 两只小熊队高级软件工程第七次作业敏捷冲刺7
团队的作业:学生信息管理系统 队员学号: 周菲(队长) 201810812007 孔繁燕 201810812001 Alpha敏捷冲刺: 1. 站立式会议照片: 2.每个人的工作: 周菲: 今天已 ...
最新文章
- 南洋理工大学科学家研发组装机器人,可以帮助用户组装椅子
- [转]七大.NET开源框架
- Dubbo-go 源码笔记(一)Server 端开启服务过程
- 简单拨号器(Android)
- 解决windows下Error:node with name rabbit already running on “XXX” 和管理页面打不开问题
- Android模拟器读取GPS串口模拟器GPS数据
- java学生宿舍管理系统,来了就点个赞再走呗,即将毕业的兄弟有福了
- 【JVM · 调优】监控及诊断工具
- wps表格宏被禁用如何解禁_wps excel宏被禁用如何启用 - 卡饭网
- Python3爬虫 爬句子迷
- 生物素-磺酸-NHS 酯,119616-38-5,Biotin-Sulfo-NHS ester
- 什么牌子的蓝牙耳机性价比高质量好?高性价比降噪蓝牙耳机推荐
- WSTMart二次开发目录说明
- 支付宝授权登录免费源码奉献
- 0315 财经爬虫实战
- Java学习打卡第七天——[再谈Collection之Set,TreeSet,泛型Generic的简介和使用]
- 码住!人工智能怎么影响教育?听这场直播就够了!
- (Modern Family S01E01) Part 7 PhilClair Dylan初访Dunphy家
- 【调剂】211中国矿业大学(徐州)2020年硕士研究生拟调剂专业
- 汉诺塔问题(三阶梵塔问题)
热门文章
- 查看Mysql数据库连接IP
- 如何对付网络爬虫 - JavaEye和网络爬虫斗争之路
- 如何修好一本家谱?怎样才能符合修谱规范?2022年修谱:利用工具
- win7怎么跳过硬盘自检_华硕品牌机win10改win7系统教程
- mysql事务内_MySQL事务
- 基于模型的设计 | Preceyes加速全球首款眼科手术机器人的开发
- Latex排版——爱思唯尔模板使用
- 计算机丢失deferrd.dll怎么解决,RdpSaPs.dll
- 详解勒让德变换与共轭函数
- linux怎么看数据库实例,Linux/Unix平台如何查看OS上存在有哪些数据库或实例