[2020.12.3周四]最长上升子序列

[2020.12.3周四]最长上升子序列LIS

hdu5256序列变换

题意:给定一个序列a[],问至少需要修改多少个数,才能使a[]严格递增。

题解:ans=n-LIS

算法:这个算法dp写需要O(n^2),dp到每个数的最长上升子序列长度,\(dp[i]=max_{j<i,a[j]<a[i]}(dp[j])\)

​ 有点偏序的意思,其实可以写离散后写树状数组二维偏序的,但太麻烦了。

​ 其实可以这样dp(如下程序),dp[i]=长度为i+1的序列的尾部最小数

​ 如果当前数比dp所有数大,就把他加入dp数组

​ 否则,它必然可以把一个dp长度尾部的数替换掉;

tag:最长上升子序列

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
const int inf =0x3f3f3f3f;
int a[maxn];
int main()
{
    int T;scanf("%d",&T);int t=0;
    while(T--)
    {
        int n;scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",a+i),a[i]-=i;//把严格递增转成非严格递增
        vector<int>dp;
        for(int i=1;i<=n;i++)
        {
            auto pos=upper_bound(dp.begin(),dp.end(),a[i]);
            if(pos==dp.end()) dp.push_back(a[i]);
            else *pos=a[i];
        }
        printf("Case #%d:\n",++t);
        printf("%d\n",n-(int)dp.size());
    }
}

E - Make It Increasing

题意:给定一个序列a[],问至少需要修改多少个数,才能使a[]严格递增,其中有k个数是不可以修改的。

题解:遇上题同理,区别在于k个不能修改的数,将a[] 分成k+1段,分段求LIS

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+100; 
const int inf=0x3f3f3f3f;
ll a[maxn],b[maxn];
int main()
{
    int n,k;
    cin>>n>>k;bool flag=true;
    for(int i=1;i<=n;i++)cin>>a[i],a[i]-=i;//a[i]>=0,非严格递增
    for(int i=1;i<=k;i++) cin>>b[i]; 
    b[0]=0;b[k+1]=n+1;a[0]=-1e9-2;a[n+1]=1e9+10;
    int  ans=0;
    for(int i=0;i<=k;i++)
    {
        int l=b[i],r=b[i+1];
        if(a[l]>a[r]) {
            cout<<"-1"<<endl;return 0;
        }
        vector<int>dp;
        for(int j=l+1;j<r;j++)//求一段a[],值在[a[l],a[r]]内的最长子序列
        {
            if(a[l]<=a[j]&&a[j]<=a[r]) 
            {
                auto pos=upper_bound(dp.begin(),dp.end(),a[j]);
                if(pos==dp.end())dp.push_back(a[j]);
                else *pos=a[j];
            }
        }
        ans+=(r-l-1)-(int)dp.size(); 
    }
    cout<<ans<<endl;
}

洛谷P2782

题意:洛谷模板题。给南北两岸友好城市的坐标,问最多有多少对城市两两不相交。

题解:排序一边城市,另一边城市求一个LIS。

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+100;
const int inf =0x3f3f3f3f;
pair<int,int> a[maxn];
int s[maxn];
int main()
{
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i].first,&a[i].second);
    sort(a+1,a+1+n);
    vector<int>dp;
    for(int i=1;i<=n;i++)
    {
        auto pos=upper_bound(dp.begin(),dp.end(),a[i].second);
        if(pos==dp.end())dp.push_back(a[i].second);
        else *pos=a[i].second;
    }
    printf("%d",(int)dp.size());
}

拓展

(1)LIS的期望

posted @ 2020-12-04 01:02  zx0710  阅读(76)  评论(0编辑  收藏  举报