HDU - 5256 序列变换(最长不下降子序列)

题意:

给出一个长度为 n n n的数组,求最少要改变多少元素的值,才能使得数组严格递增。

题解:

一开始瞬间想到最长上升子序列,因为 n n n比较大,所有只能用贪心+二分的 O ( n l o g n ) O(nlogn) O(nlogn)复杂度的算法写,然后wa了。

后来想了想,其实不对,例如:1 2 3 3 4,最长上升子序列为4,那么答案只需修改1个,而实际上是修改2个。

因为要求 a i + 1 > a i a_{i+1}>a_i ai+1>ai ,那么 a i + 1 − 1 ≥ a i a_{i+1}-1 \geq a_i ai+11ai 那么 a i + 1 − 1 − i ≥ a i − i a_{i+1}-1-i \geq a_i-i ai+11iaii ,推出 a i + 1 − ( i + 1 ) ≥ a i − i a_{i+1}-(i+1) \geq a_i-i ai+1(i+1)aii

那么设 b i = a i − i b_i=a_i-i bi=aii 那么只需求出 b b b 数组的最长不下降子序列即可。最长不下降子序列只需在最长上升子序列的代码中修改二分条件即可。

代码:

#pragma GCC diagnostic error "-std=c++11"
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int MAXN=2e5+5;
const int inf=0x3f3f3f3f;
int dp[MAXN];
int a[MAXN];
int main()
{
    int t;
    scanf("%d",&t);
    int kase=1;
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i = 0; i <= n; i++)
            dp[i]=inf;
        for(int i = 0; i < n; i++)
        {
            scanf("%d",&a[i]);
            a[i]-=i;
        }
        for(int i = 0; i < n; i++)
        {
            *upper_bound(dp,dp+n,a[i])=a[i];
        }
        int ans=lower_bound(dp,dp+n,inf)-dp;
        ans=n-ans;
        printf("Case #%d:\n",kase++);
        printf("%d\n",ans);
    }
}
posted @ 2021-07-21 15:05  TheBestQAQ  阅读(48)  评论(0)    收藏  举报