序列变换
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。
Output
对于每组数据,先输出一行 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#include #include #include #include #include using namespace std;const int MAXN = 1e5 + 100;int num[MAXN];int dp[MAXN];vector 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:\n%d\n", ++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:\n%d\n", ++kase, N - ans - 1); } return 0;}