序列变换
Accepts: 720
Submissions: 3074
Time Limit: 4000/2000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
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
来源: <http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=600&pid=1003>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
int n;
int nums[100010], numsc[100010];
int main() {
int T;
cin >> T;
for(int nq = 0; nq != T; ++nq) {
printf("Case #%d:\n", nq+1);
cin >> n;
for(int i = 0; i != n; ++i) {
// cin >> nums[i];
scanf("%d", &nums[i]);
}
int beginK = -1, endK = 5000000, midK;
bool can;
while(endK - beginK > 1) {
midK = (beginK + endK) / 2;
for(int i = 0; i != n; ++i) {
numsc[i] = nums[i];
}
numsc[0] -= midK;
can = true;//当前K可行
for(int i = 1; i != n; ++i) {
if(numsc[i] > numsc[i-1]) {
if(numsc[i] - numsc[i-1] > midK) {
numsc[i] -= midK;
}
else {
numsc[i] = numsc[i-1] + 1;
}
}
else if(midK < numsc[i-1] - numsc[i] + 1) {
beginK = midK;
can = false;//当前K不可行
break;
}else {
numsc[i] = numsc[i-1] + 1;
}
}
if(can) endK = midK;
}
cout << endK << endl;
}
return 0;
}
二分答案
时间: 2024-10-05 22:05:42