序列变换
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1309 Accepted Submission(s): 570
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
思路:
1、随着cost(A,B)的值越大,我们可能得到满足条件的序列的机会就越大,那么根据这个递增性质,我们考虑二分cost(A,B)这个值。
2、对应当前二分出来的Cost(A,B)值mid;我们贪心的处理序列A:
①很显然,我们是想要将存在a【i】>a【j】(i<j)的两个数转换成:a【i】<a【j】的情况,那么考虑将a【i】减小,将a【j】增大即可。
②那么对于一部分其他数,我们存在相互制约的关系,所以我们应当有一个合理的顺序来处理这个数组。
③那么考虑将第一个数直接减少mid.然后从第二个数向后扫,如果当前a【i】>b【i-1】,那么b【i】=a【i】-mid,如果发现b【i】此时减的过多了,那么对应b【i】=b【i-1】+1,使得序列尽可能的紧凑(虽然此时设定为b【i-1】+2也可以,但是不足够贪心,我们希望序列尽可能的紧凑起来)如果当前a【i】<b【i-1】,那么我们希望将a【i】增大,那么对应b【i】=a【i】+mid,此时若b【i】>b【i-1】,那么我们仍然保持希望序列紧凑的思想,设定b【i】=b【i-1】+1;
④依次类推得到一个序列b【】,然后判断序列b【】是否严格递增。
⑤对应当前mid值得到的序列是否可行,判断接下来二分的区间,一直二分下去,维护最终答案输出即可。
Ac代码:
#include<stdio.h>
#include<string.h>
using namespace std;
int a[1060000];
int b[1060000];
int n;
int Slove(int mid)
{
for(int i=1;i<=n;i++)
{
if(i==1)b[i]=a[i]-mid;
else
{
if(a[i]>b[i-1])
{
b[i]=a[i]-mid;
if(b[i]<=b[i-1])b[i]=b[i-1]+1;
}
else
{
b[i]=a[i]+mid;
if(b[i]>b[i-1])b[i]=b[i-1]+1;
}
}
}
int flag=0;
for(int i=2;i<=n;i++)
{
if(b[i]>b[i-1])continue;
else flag=1;
}
if(flag==0)return 1;
else return 0;
}
int main()
{
int kase=0;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int ans=0;
int l=0;
int r=10000000;
while(r-l>=0)
{
int mid=(l+r)/2;
if(Slove(mid)==1)
{
r=mid-1;
ans=mid;
}
else l=mid+1;
}
printf("Case #%d:\n",++kase);
printf("%d\n",ans);
}
}