hdu5248序列变换(二分+贪心)基础题

题意(中文的直接粘题意吧)
                                                                                      序列变换


Problem Description
给定序列A={A1,A2,...,An}, 要求改变序列A中的某些元素,形成一个严格单调的序列B(严格单调的定义为:Bi

我们定义从序列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


思路:

      思路简单一下就能想到,二分当前答案,对于当前答案,从头开始贪心,能小就尽可能的小就行了。


#include
#include

int A[100005] ,B[100005];

int maxx(int x ,int y)
{
    return x > y ? x : y;
}

int jude(int k ,int n)
{
    for(int i = 1 ;i <= n ;i ++)
    {
        if(i == 1) B[i] = A[i] - k;
        else
        {
            if(A[i] > B[i-1]) B[i] = maxx(B[i-1]+1 ,A[i] - k);
            else
            {
                if(A[i] + k > B[i-1]) B[i] = B[i-1]+1;
                else return 0;
            }
        }

    }
    return 1;
}

int main ()
{
    int t ,n ,cas = 1 ,i;
    scanf("%d" ,&t);
    while(t--)
    {
        scanf("%d" ,&n);
        for(i = 1 ;i <= n ;i ++)
        scanf("%d" ,&A[i]);
        int low = 0 ,up = 1000005 ,mid ,ans;
        while(low <= up)
        {
            mid = (low + up) >> 1;
            if(jude(mid ,n)) ans = mid ,up = mid - 1;
            else low = mid + 1;
        }
        printf("Case #%d:\n" ,cas ++);
        printf("%d\n" ,ans);
    }
    return 0;
}





你可能感兴趣的:(ACM_水题,ACM_贪心)