http://acm.hdu.edu.cn/showproblem.php?pid=5248
|
序列变换Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1076 Accepted Submission(s): 492
Problem Description
给定序列
A={A
我们定义从序列A到序列B变换的代价为 cost(A,B)=max(|A 请求出满足条件的最小代价。 注意,每个元素在变换前后都是整数。
Input
第一行为测试的组数
T(1≤T≤10)
对于每一组: 第一行为序列A的长度 N(1≤N≤10 序列A中的每个元素的值是正整数且不超过 10
Output
对于每一个测试样例,输出两行:
第一行输出:"Case #i:"。i代表第 i 组测试数据。 第二行输出一个正整数,代表满足条件的最小代价。
Sample Input
Sample Output
Source
|
思路:
可证得:a[i]-i 非递减序列。
因为a[i]<a[i+1],且a[i],a[i+1]都是整数,所以有a[i+1]-1>=a[i],整理得a[i+1]-(i+1)>=a[i]-i。
此时令b[i]=a[i]-i,则可以求出b[i]的最长不下降子序列的长度len,
最后用n-len即为需要改变的最少的元素个数。
Code:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MYDD=1103+1e6;
int ori[MYDD];//original
int xin[MYDD];
int main() {
int TT;
scanf("%d",&TT);
int Kcase=1;
while(TT--) {
int n,m;
scanf("%d",&n);
for(int j=0; j<n; j++)
scanf("%d",&ori[j]);
for(int j=0; j<n; j++)
ori[j]-=j;
int ans=1;
xin[0]=ori[0];//LIS 求解
for(int j=1; j<n; j++) {
if(ori[j]>=xin[ans-1]) xin[ans++]=ori[j];
else {
int temp=upper_bound(xin,xin+ans,ori[j])-xin;//二分算法的 std 调用
//为什么 *upper_bound(xin,xin+ans,ori[j]) 就不对
xin[temp]=ori[j];
}
}
printf("Case #%d:\n%d\n",Kcase++,n-ans);
}
return 0;
}