序列变换
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 774 Accepted Submission(s): 359
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
分析:二分枚举最大改变量,对于改变量mid,b[1]-=mid,然后比较接下来的b[i]如果比b[i-1]大,则看b[i]-mid是否大于b[i-1],是的话b[i]-=mid,否则b[i]=b[i-1]+1;
如果b[i]小于等于b[i-1],看b[i]=b[i-1]+1是否与a[i]的差值小于等于mid,是的话b[i]=b[i-1]+1;否则的话b[i]没法改变....mid不成立
程序:
#include"stdio.h" #include"string.h" #include"stdlib.h" #include"algorithm" #include"queue" #include"math.h" #include"iostream" #include"vector" #define M 100009 #define inf 0x3f3f3f3f #define eps 1e-9 #define PI acos(-1.0) #include"map" #include"vector" #include"set" #include"string" using namespace std; int a[M],b[M]; int Fabs(int a) { if(a<0) a=-a; return a; } int check(int mid,int n) { for(int i=1;i<=n;i++) b[i]=a[i]; b[1]-=mid; for(int i=2;i<=n;i++) { if(a[i]>b[i-1]) { if(a[i]-mid>b[i-1]) b[i]-=mid; else b[i]=b[i-1]+1; } else { if(b[i-1]+1-a[i]<=mid) b[i]=b[i-1]+1; else return 0; } } return 1; } int main() { int T,kk=1; cin>>T; while(T--) { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int l=0; int r=1000001; int mid; int ans=-1; while(l<=r) { mid=(l+r)/2; if(check(mid,n)) { ans=mid; r=mid-1; } else l=mid+1; } printf("Case #%d: ",kk++); printf("%d ",ans); } return 0; }