序列变换
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1200 Accepted Submission(s): 448
Problem Description
我们有一个数列A1,A2...An,你现在要求修改数量最少的元素,使得这个数列严格递增。其中无论是修改前还是修改后,每个元素都必须是整数。 请输出最少需要修改多少个元素。
Input
第一行输入一个T(1≤T≤10),表示有多少组数据
每一组数据:
第一行输入一个N(1≤N≤105),表示数列的长度
第二行输入N个数A1,A2,...,An。
每一个数列中的元素都是正整数而且不超过106。
每一组数据:
第一行输入一个N(1≤N≤105),表示数列的长度
第二行输入N个数A1,A2,...,An。
每一个数列中的元素都是正整数而且不超过106。
Output
对于每组数据,先输出一行
Case #i:
然后输出最少需要修改多少个元素。
Case #i:
然后输出最少需要修改多少个元素。
Sample Input
2
2
1 10
3
2 5 4
Sample Output
Case #1:
0
Case #2:
1
Source
题解:
改变系列使成为单调递增子序列;那么只需要dp[i]-dp[j]>=i-j就好了;再加上单调递增子序列的求法;
dp[i]-dp[j]>=i-j即为dp[i]-i>=dp[j]-j;
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> using namespace std; const int MAXN = 1e5 + 100; int num[MAXN]; int dp[MAXN]; vector<int>vec; /* int main(){ int T, N, kase = 0; scanf("%d", &T); while(T--){ vec.clear(); scanf("%d", &N); for(int i = 0; i < N; i++){ scanf("%d", num + i); num[i] -= i; if(upper_bound(vec.begin(), vec.end(), num[i]) == vec.end()){ vec.push_back(num[i]); } else{ int p = upper_bound(vec.begin(), vec.end(), num[i]) - vec.begin(); vec[p] = num[i]; } } printf("Case #%d: %d ", ++kase, N - vec.size()); } return 0; } */ int main(){ int T, N, kase = 0; scanf("%d", &T); while(T--){ scanf("%d", &N); memset(dp, 0, sizeof(dp)); int ans = 0; for(int i = 0; i < N; i++){ scanf("%d", num + i); for(int j = 0; j < i; j++){ if(num[i] - num[j] >= i - j){ dp[i] = dp[j] + 1; ans = max(ans, dp[i]); } } } printf("Case #%d: %d ", ++kase, N - ans - 1); } return 0; }