HDU-P5248:序列变换[二分答案]
HDU-P5248:序列变换[二分答案]
题目
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
思路
题目也是看了很久才明白意思,开始还以为是一个排序的问题,结果WA了几发,万般无奈之下上网查了查题解,看到二分时的我恍然大悟。
在这个题目里主要要想明白的是不是根据序列求出答案,而是拿着可能的答案去试是否满足题意,二分法显然能胜任这样的工作。
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
const int MAXN = 100005;
using namespace std;
int ans, a[MAXN], b[MAXN], len;
int cnt = 0;
bool judge(int x) {
memcpy(b, a, sizeof(a)); //注意不能破坏原序列,故操作在新序列中进行
b[0]-=x; //前面的元素值越小,越有利
for(int i = 1; i < len; ++i) { //将b[i]构造成一个尽可能小的数字
if(b[i]<=b[i-1]) {
if(b[i]+x>b[i-1]) b[i] = b[i-1]+1;
else return false;
}
else if(b[i]-x>b[i-1]) b[i] = b[i]-x;
else b[i] = b[i-1]+1;
}
return true;
}
int main(void)
{
int T, ans;
scanf("%d", &T);
while(T--) {
scanf("%d", &len);
for(int i = 0; i < len; ++i)
scanf("%d", &a[i]);
int L = 0, R = 1000005, mid; //L和R的值根据题目给出的范围得出
while(L <= R) {
mid = (L+R)/2;
if(judge(mid)) {
ans = mid;
R = mid-1;
}
else
L = mid+1;
}
printf("Case #%d:\n%d\n", ++cnt, ans);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通