bzoj 1049: [HAOI2006]数字序列(DP+DP)
1049: [HAOI2006]数字序列
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1848 Solved: 801
[Submit][Status][Discuss]
Description
现在我们有一个长度为n的整数序列A。但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列。
但是不希望改变过多的数,也不希望改变的幅度太大。
Input
第一行包含一个数n,接下来n个整数按顺序描述每一项的键值。n<=35000,保证所有数列是随机的
Output
第一行一个整数表示最少需要改变多少个数。 第二行一个整数,表示在改变的数最少的情况下,每个数改变
的绝对值之和的最小值。
Sample Input
Sample Output
第一问很简单,对于下标x<y,当且仅当a[y]-a[x]>=y-x时,下标y和x的两个数就可以都不动,否则一定有一个要修改
设b[i] = a[i]-i,F[i]表示以b[i]结尾的LIS长度,答案就是n-F[n]
第二问可以证出对于下标x<y,且F[x]+1=F[y],那么一定存在一个k∈(x, y)满足
(x, k]里的数全部修改成a[x]+1, a[x]+2,a[x]+3,…,a[x]+k-x;
(k, y)里的数全部修改成a[y]-(y-k+1),…,a[y]-2,a[y]-1
即[x, k]内所有的a[]连续,(k, y]内所有的a[]连续时幅度最优
设dp[i]表示前i个数修改成严格递增序列的最小幅度,其中第i个数a[i]不变
那么有dp[i] = min(dp[j]+Mincost(k), j<i && F[j]+1=F[i] && b[j]<=b[i])
其中Mincost也可以直接暴力k∈(x, y),这样复杂度为O(n^3),但是由于数据完全随机,所以能进行转移的(i, j)非常少!
不过为了保证正确,要在数组最前面加一个非常小的数,在数组最后面加一个非常大的数
O(可以过),程序还可以再优化
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define LL long long
LL b[35005], a[35005], bet[35005], F[35005], dp[35005];
int main(void)
{LL n, i, len, l, j, k, r, m, now, Min;scanf("%lld", &n);for(i=1;i<=n;i++){scanf("%lld", &a[i]);b[i] = a[i]-i;}len = 0;a[0] = b[0] = -1e10;a[n+1] = b[n+1] = 1e10;for(i=1;i<=n+1;i++){if(len==0 || bet[len]<=b[i])bet[++len] = b[i], F[i] = len;else{l = 1, r = len;while(l<r){m = (l+r)/2;if(bet[m]<=b[i])l = m+1;elser = m;}bet[r] = b[i];F[i] = r;}}memset(dp, 62, sizeof(dp));printf("%lld\n", n-(len-1));dp[0] = 0;for(i=1;i<=n+1;i++){for(j=0;j<=i-1;j++){if(F[j]+1!=F[i] || b[j]>b[i])continue;now = 0;for(k=j+1;k<=i-1;k++)now += abs(a[k]-(a[i]-(i-k)));Min = now;for(k=j+1;k<=i-1;k++){now = now-abs(a[k]-(a[i]-(i-k)))+abs(a[k]-(a[j]+k-j));Min = min(Min, now);}dp[i] = min(dp[i], dp[j]+Min);}}printf("%lld\n", dp[n+1]);return 0;
}
/*
5
1 1 1 1 1
*/
bzoj 1049: [HAOI2006]数字序列(DP+DP)相关推荐
- bzoj1049[HAOI2006]数字序列
1049: [HAOI2006]数字序列 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1813 Solved: 789 [Submit][Sta ...
- [BZOJ 1046] [HAOI2007] 上升序列 【DP】
题目链接:BZOJ - 1046 题目分析 先倒着做最长下降子序列,求出 f[i],即以 i 为起点向后的最长上升子序列长度. 注意题目要求的是 xi 的字典序最小,不是数值! 如果输入的 l 大于最 ...
- 数字游戏——数位dp问题
数字游戏 数位dp思路: 首先考虑第一个数字能填什么,预处理第一个数字能填的数(除去边界),然后去判断边界,即让循环往下走. 代码 #include <iostream> #include ...
- SCU - 1114 数字三角(dp入门ing)
SCU - 1114 数字三角(dp入门ing) 下图是个数字三角,请编写一个程序计算从顶部至底部某处一条路径,使得该路径所经过的数字总和最大. 7 3 8 8 1 0 2 7 4 4 1. 每一步可 ...
- BZOJ 2073: [POI2004]PRZ( 状压dp )
早上这道题没调完就去玩NOI网络同步赛了.... 状压dp , dp( s ) 表示 s 状态下所用的最短时间 , 转移就直接暴力枚举子集 . 可以先预处理出每个状态下的重量和时间的信息 . 复杂度是 ...
- BZOJ 1003 物流运输 最短路+dp
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1003 题目大意: 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才 ...
- leetcode 376. 摆动序列(dp)
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列.第一个差(如果存在的话)可能是正数或负数.少于两个元素的序列也是摆动序列. 例如, [1,7,4,9,2,5] 是一个摆动序列, ...
- BZOJ 2442: [Usaco2011 Open]修剪草坪( dp )
dp dp[ i ] 表示第 i 个不选 , 前 i 个的选择合法的最小损失 , dp[ i ] = min( dp[ j ] ) ( max( 0 , i - 1 - k ) <= j < ...
- 【BZOJ 1222】 [HNOI2001] 产品加工(DP)
Description 某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时由两台机 ...
最新文章
- 安装上传下载插件,jdk及redis
- MySQL写十行_python 十行代码系列(四):操作mysql插入测试数据
- 狄利克雷卷积_一些狄利克雷卷积性质的证明
- mysql数据结构_mysql的底层数据结构
- python深度学习第四讲——python神经网络参数更新
- 互联网创业公司残酷一幕:全员降薪,裁员凶猛与一夜解散
- 如何用 10 句话激怒程序猿?
- 如何利用PHOTOSHOP将图片旋转45度
- 谷歌软件工程师_这是我曾经在Google担任软件工程师的简历。
- google 浏览器下载历史版本的方法
- 在销量压力下,国产手机开始降价了,但还没有放下最后的面子
- java 读取Excel
- [ZZ]浅谈中国B2C珍珑棋局
- [Neuronal Dynamics 笔记] I Foundations of Neuronal Dynamics - 2 The Hodgkin-Huxley Model
- 漏洞预警| vm2 任意代码执行漏洞
- strlen函数的用法和细节
- 容错服务器怎么装系统,容错服务器安装手册.doc
- 学生学分管理系统(C语言)
- EXSi不小心直通所有网卡
- AssetStudio/UnityStudio UABE等 破解Unity游戏