序列变换 HDU - 5256
序列变换 HDU - 5256
题目
我们有一个数列A1,A2...An,你现在要求修改数量最少的元素,使得这个数列严格递增。其中无论是修改前还是修改后,每个元素都必须是整数。
请输出最少需要修改多少个元素。
input
第一行输入一个T(1≤T≤10),表示有多少组数据
每一组数据:
第一行输入一个N(1≤N≤105),表示数列的长度
第二行输入N个数A1,A2,...,An。
每一个数列中的元素都是正整数而且不超过106。
output
对于每组数据,先输出一行
Case #i:
然后输出最少需要修改多少个元素。
Sample Input
2
2
1 10
3
2 5 4
Sample Output
Case #1:
0
Case #2:
1
分析
一开始很容易就想到 \(\mathrm{LIS}\) 。先算出 \(\mathrm{LIS}\) 的长度,然后序列总长度减去 \(\mathrm{LIS}\) 的长度就行了。
但是隐隐间觉得有点不对,留意到题目中的严格递增,就想到了如果连续几个都是相同的怎么办。然后就举出了反例。
例如:1 2 2 2 3 。这个序列的 \(\mathrm{LIS}\) 为 1 2 3。按照上面的的方法算出的答案是 2 。但实际上,我们要修改成 1 2 3 4 5。要修改的个数为 3。
但我们还是想要往 \(\mathrm{LIS}\) 上靠,仔细分析一下,我们修改后的整个数组要满足如下的条件:
\]
怎么往 \(\mathrm{LIS}\) 上靠呢?\(\mathrm{LIS}\) 最后的式子是不是要满足:
\]
第一个式子中的 \(1\) 是不是有点碍事,留意到两边其实可以做一个操作:
\]
两边都可以减去一个 \(i\) , 那么就可以转化到 \(\mathrm{LIS}\) 的做法了。
再留意到 \(n \le 10^5,T \le 10\) , \(O(n^2)\) 的复杂度肯定是接受不了,要对朴素的做法进行一些优化。
其实也是一个贪心的做法。我们可以去维护这样一个 \(dp\) 数组。不妨设 \(len\) 为 \(dp\) 数组的长度。在遍历数组 \(arr\) 的时候,有两种情况:
- \(arr[i] \ge dp[len - 1]\),把 \(arr[i]\) 加到 \(dp\) 数组的结尾。
- \(arr[i] < dp[len - 1]\),二分查找 \(dp\) 数组里,第一个大于 \(arr[i]\) 数字,然后替换成 \(arr[i]\)。
然后,最后 \(len\) 就是 \(\mathrm{LIS}\) 的长度。
看得出来,数组 \(dp\) 本身就在维护一个尽可能长的上升序列,第一个操作很好理解,那么对于第二个操作,由贪心我们可以知道,如果有几个序列,那么序列末尾的数字越小,那么它能成为 \(\mathrm{LIS}\) 的概率越大?所以第二个操作就是不断地在保证它在成为 \(\mathrm{LIS}\)。如果但是如果替换的不是最后一个呢?由于是替换,不是增加或者减小,所以这对于最后的结果并没有影响,所以替换前面的数字并没有影响。(这造成了 \(dp\) 数组并不是 \(\mathrm{LIS}\) )。
所以用二分就能把 \(\mathrm{LIS}\) 优化到 \(O(n \log n)\)。
代码
#include <bits/stdc++.h>
#define lowbit(x) ((x)&(-x))
#define mem(i, a) memset(i, a, sizeof(i))
#define sqr(x) ((x)*(x))
typedef long long ll;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 1e5 + 7;
using namespace std;
int arr[maxn], dp[maxn];
int main(void){
#ifdef ljxtt
freopen("data.in", "r", stdin);
#endif
int T; scanf("%d", &T);
int cases = 1;
while(T--){
int n; scanf("%d", &n);
for(int i = 0; i < n; i++){
scanf("%d", &arr[i]);
arr[i] -= i;
}
int len = 0;
dp[0] = arr[0];
for(int i = 1; i < n; i++){
if(arr[i] >= dp[len])
dp[++len] = arr[i];
else
*upper_bound(dp, dp + len + 1, arr[i]) = arr[i];
}
printf("Case #%d:\n%d\n", cases++, n - len - 1);
}
return 0;
}
序列变换 HDU - 5256的更多相关文章
- hdu 5256 序列变换 (LIS变形)
序列变换 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- 51nod 1294 :修改数组 && HDU 5256:序列变换
1294 修改数组 题目来源: HackerRank 基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 收藏 取消关注 给出一个整数数组A,你可以将任何一个数修 ...
- LIS 2015百度之星初赛2 HDOJ 5256 序列变换
题目传送门 题意:中文题面 分析:LIS(非严格):首先我想到了LIS,然而总觉得有点不对:每个数先减去它的下标,防止下面的情况发生:(转载)加入序列是1,2,2,2,3,这样求上升子序列是3,也就是 ...
- 2015年百度之星初赛(1) --- C 序列变换
序列变换 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 序列变换(hdu5248)
序列变换 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 序列变换(Lis变形)
序列变换 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- 51Nod 欢乐手速场1 B 序列变换[容斥原理 莫比乌斯函数]
序列变换 alpq654321 (命题人) 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 lyk有两序列a和b. lyk想知道存在多少对x,y,满足以下两个条件. 1:gcd( ...
- 二分搜索 2015百度之星初赛1 HDOJ 5248 序列变换
题目传送门 /* 二分搜索:在0-1e6的范围找到最小的max (ai - bi),也就是使得p + 1 <= a[i] + c or a[i] - c 比赛时以为是贪心,榨干智商也想不出来:( ...
- luogu P3411 序列变换
链接 P3411 序列变换 如果要最小化答案,那么就最大化不移动的数. 那么不移动的子序列一定是最后答案的一段连续区间,而移动的数我们是一定有办法把他们还原的. 设\(f_{i}\)表示\(i\)点的 ...
随机推荐
- vue插槽的使用
一.插槽的基本使用 二.具名插槽的使用 三.编译作用域的例子 四.作用域插槽 一.插槽的基本使用 1.插槽的基本使用<slot></slot> 2.插槽的默认值 ...
- php设计模式之单例实例代码
<?php header("Content-type:text/html;charset=utf-8"); /** * 第一步,分别实例化 */ /*class Single ...
- Zeta(2) 有图版
我很早就一直想写一篇文章,跟大家聊一聊: $$\frac{1}{1^2}+\frac{1}{2^2} +\frac{1}{3^2} +\frac{1}{4^2} +\frac{1}{5^2} +\cd ...
- scrapy 框架基本使用
scrapy简介: Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络抓取 ...
- 为什么hadoop中用到的序列化不是java的serilaziable接口去序列化而是使用Writable序列化框架
继上一个模块之后,此次分析的内容是来到了Hadoop IO相关的模块了,IO系统的模块可谓是一个比较大的模块,在Hadoop Common中的io,主要包括2个大的子模块构成,1个是以Writable ...
- 使用datatable动态添加的顺序与存储的顺序不一致
原因是datatable在展示数据的时候帮助我们排序了 将其禁止排序即可:"ordering":false
- 「题解」「UOJ-164」「清华集训2015」V
目录 题目 原题目 简要题目 正解 这道题题目简洁新颖,吸引读者阅读兴趣... 题目 原题目 点这里 简要题目 需要你维护长度为n的序列并支持下列操作: 区间加法: 区间赋值: 区间每个 \(a_i\ ...
- hackinglab 冒充登录用户
首先进入网页会发现 直接用bp进行抓包然后会发现一个字母是Login这个是登录的意思发现这个字母等于0我们大胆的猜测一下这个字母等于0代表的是没有登陆而如果这个字母是1或者是2的时候就是登录了然后我们 ...
- 7-8 Left-pad
思路 注意读入和输出格式 如果用fgets读入的话会带上回车,输出的时候一定不要输出了双回车 并且此时的length也会比原始长度多了一,要注意长度比较,这里容易出错 代码 #include < ...
- 1.什么是Mybatis?
在学习之前我们要回顾以下知识 JDBC Mysql java基础 Maven Junit 什么是 MyBatis? MyBatis 是一款优秀的持久层框架MyBatis 避免了几乎所有的 JDBC 代 ...