序列变换(二分,最小化最大值)

序列变换

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 950    Accepted Submission(s): 438

Problem Description
给定序列A={A1,A2,...,An}, 要求改变序列A中的某些元素,形成一个严格单调的序列B(严格单调的定义为:Bi<Bi+1,1i<N)。
我们定义从序列A到序列B变换的代价为cost(A,B)=max(|AiBi|)(1iN)
请求出满足条件的最小代价。
注意,每个元素在变换前后都是整数。
 
Input
第一行为测试的组数T(1T10).
对于每一组: 第一行为序列A的长度N(1N105),第二行包含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

题解:注意范围是0到1e5,脑子抽了,1到1e5半天没发现错误:

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN = 1e5 + 100;
int num[MAXN];
int arr2[MAXN];
int N;

bool js(int x){
    int pre, cur;
    pre = num[0];
    for(int i = 1; i <= N; i++){
        cur = num[i];
        if(cur > pre){
            cur = max(cur - x, pre + 1);
        }
        else{
            if(cur + x <= pre)return false;
            cur = pre + 1;
        }
        pre = cur;
    }
    return true;
}

int erfen(int l, int r){
    int mid, ans = N; 
    
    while(l <= r){
        mid = (l + r) >> 1;
        if(js(mid)){
            ans = mid;
            r = mid - 1;
        }
        else l = mid + 1;
    }
    
    return ans;
}
int main(){
    int T, kase = 0;
    scanf("%d", &T);
    num[0] = -0x3f3f3f3f;
    while(T--){
        scanf("%d", &N);
        for(int i = 1; i <= N; i++){
            scanf("%d", num + i);
        }
        printf("Case #%d:
%d
", ++kase, erfen(0, 3000000));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/handsomecui/p/5379622.html