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)。
请求出满足条件的最小代价。
注意,每个元素在变换前后都是整数。
我们定义从序列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。
对于每一组:
第一行为序列A的长度N(1≤N≤105),第二行包含N个数,A1,A2,...,An.
序列A中的每个元素的值是正整数且不超过106。
Output
对于每一个测试样例,输出两行:
第一行输出:"Case #i:"。i代表第 i 组测试数据。
第二行输出一个正整数,代表满足条件的最小代价。
第一行输出:"Case #i:"。i代表第 i 组测试数据。
第二行输出一个正整数,代表满足条件的最小代价。
Sample Input
2
2
1 10
3
2 5 4
Sample Output
Case #1:
0
Case #2:
1
Source
Recommend
对于给定的范围,我们可以二分查找x看是否a序列加减x后能否满足递增
有三种情况
1.如果a[i]+x < temp 即在这个范围里面是肯定可以的,temp就更新成下面需要判断的序列对
2.如果a[i] - x >= temp a[i]即使小到最小仍旧比后面一个数大,说明不可行
3.其他情况为了保证严格递增 temp--
二分左闭右开
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; int n; int a[1000005]; bool judge(int x){ int temp = a[n] + x; for(int i = n - 1; i >= 1; i--){ if(a[i] + x < temp){ temp = a[i] + x; } else if(a[i] - x >= temp) return false; else temp--; } return true; } int main() { int t; scanf("%d",&t); for(int cas = 1; cas <= t; cas++){ scanf("%d",&n); for(int i = 1; i <= n ;i ++) scanf("%d",&a[i]); int l = 0,r = 1000000; while(l < r){ int mid = (l + r ) >> 1; if(judge(mid)){ r = mid; } else l = mid + 1; } printf("Case #%d: %d ",cas,l); } return 0; }