hdu 5248 序列变换(二分枚举)

Problem Description

给定序列A={A1,A2,...,An}, 要求改变序列A中的某些元素,形成一个严格单调的序列B(严格单调的定义为:Bi<Bi+1,1≤i<N)。

我们定义从序列A到序列B变换的代价为cost(A,B)=max(|Ai−Bi|)(1≤i≤N)。

请求出满足条件的最小代价。

注意,每个元素在变换前后都是整数。

Input

第一行为测试的组数T(1≤T≤10).

对于每一组:
第一行为序列A的长度N(1≤N≤105),第二行包含N个数,A1,A2,...,An.
序列A中的每个元素的值是正整数且不超过106。

Output

对于每一个测试样例,输出两行:

第一行输出:"Case #i:"。i代表第 i 组测试数据。

第二行输出一个正整数,代表满足条件的最小代价。

Sample Input

2
2
1 10
3
2 5 4

Sample Output

Case #1: 0
Case #2: 1

Source

2015年百度之星程序设计大赛 - 初赛(1)

二分枚举最小的代价。从后往前枚举判断序列是否为单调递减

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 #include<stdlib.h>
 6 #include<cmath>
 7 #include<algorithm>
 8 using namespace std;
 9 #define N 100006
10 #define inf 1<<30
11 int n;
12 int a[N];
13 bool solve(int mid){
14     int tmp=a[n]+mid;
15     for(int i=n-1;i>=1;i--){
16         if(abs(tmp-1-a[i])<=mid){
17             tmp=tmp-1;
18         }
19         else if(tmp-1>=a[i]){
20             tmp=a[i]+mid;
21         }
22         else{
23              return false;
24         }
25     }
26     return true;
27 }
28 int main()
29 {
30     int ac=0;
31     int t;
32     scanf("%d",&t);
33     while(t--){
34         scanf("%d",&n);
35         for(int i=1;i<=n;i++){
36             scanf("%d",&a[i]);
37         }
38         int low=0;
39         int high=inf;
40         while(low<high){
41             int mid=(low+high)>>1;
42             if(solve(mid)){
43                 high=mid;
44             }
45             else{
46                 low=mid+1;
47             }
48         }
49         printf("Case #%d:\n",++ac);
50         printf("%d\n",low);
51
52     }
53     return 0;
54 }

时间: 2024-10-06 13:37:40

hdu 5248 序列变换(二分枚举)的相关文章

hdu 5248 序列变换【二分】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5248 分析:这道题是2015百度之星初赛1的3题 当时队友做的,后来也做了一下,可以用二分来做,另外还有一点小贪心, 因为题目数据范围不超过10^6,那么x=二分[0,10^6],使序列里的每一个数变化范围 值为x,求使序列变为升序的最小x值 另外贪心就是,我每一个数尽量X[i]变为X[i-1]+1,因为序列要升序,这样可以保证 对X[i+1]要求X[i+1]>X[i]的条件变得宽松, 献上代码:

HDU ACM 5248 序列变换-&gt;二分代价+贪心

分析:二分代价,由于序列是单增的,我们使前面一个数相对取最小,这样后面的数变化的值也能相对较小(贪心). #include<iostream> using namespace std; #define N 100010 #define max(a,b) ((a)>(b)?(a):(b)) int num[N],tmp[N],n; bool valid(int cost) { int i; for(i=1;i<=n;i++) tmp[i]=num[i]; tmp[1]=tmp[1]-

hdu 5248 序列变换

中文题意,略(但弱鸡的我还是把题目读错了,一直到读题解的时候才发现,弱鸡总会读错题目,我以为跑一下lis就行了,太天真) 但现在还是没有想到为什么会用二分(虽然大家都是这么说的,而且这是二分专题,emmm) #include <set> #include <map> #include <queue> #include <stack> #include <math.h> #include <vector> #include <st

BC 2015年百度之星程序设计大赛 - 初赛(1)(序列变换-二分答案贪心)

序列变换 Accepts: 816 Submissions: 3578 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description 给定序列A={A 1 ,A 2 ,...,A n } , 要求改变序列A中的某些元素,形成一个严格单调的序列B(严格单调的定义为:B i <B i+1 ,1≤i<N ). 我们定义从序列A到序列B变换的代价为cost(A,B

hdu 5256 序列变换 (LIS变形)

序列变换 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 519    Accepted Submission(s): 245 Problem Description 我们有一个数列A1,A2...An,你现在要求修改数量最少的元素,使得这个数列严格递增.其中无论是修改前还是修改后,每个元素都必须是整数. 请输出最少需要修改多少个元素.

hdu 5256 序列变换

最长上升子序列 nlogn;也是从别人的博客学来的 #include<iostream> #include<algorithm> #define maxn 100000+5 using namespace std; int n; int a[maxn]; int solve(int b[],int l) { int f[maxn];//f[i]表示子序列长度为i+1的序列中,末尾元素最小的元素的值 int k=0; f[k++]=b[0]; for(int i=1;i<l;i

hdu 5256 序列变换(LIS最长上升子序列)

Problem Description 我们有一个数列A1,A2...An,你现在要求修改数量最少的元素,使得这个数列严格递增.其中无论是修改前还是修改后,每个元素都必须是整数. 请输出最少需要修改多少个元素. Input 第一行输入一个T(1≤T≤10),表示有多少组数据 每一组数据: 第一行输入一个N(1≤N≤105),表示数列的长度 第二行输入N个数A1,A2,...,An. 每一个数列中的元素都是正整数而且不超过106. Output 对于每组数据,先输出一行 Case #i: 然后输出

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&#39;s problem(manacher+二分/枚举)

HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分相同,第一部分与第二部分对称. 现在给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法,求出以第i个点为中心的回文串长度,记录到数组p中 要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,也就是说,左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也是一样. 因为我们已经记录下来以

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&amp;#39;s problem(manacher+二分/枚举)

pid=5371">HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分同样,第一部分与第二部分对称. 如今给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法.求出以第i个点为中心的回文串长度.记录到数组p中 要满足题目所要求的内容.须要使得两个相邻的回文串,共享中间的一部分,也就是说.左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也