zoukankan      html  css  js  c++  java
  • [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:
    ",++t);
            printf("%d
    ",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的期望

  • 相关阅读:
    Linux内核邮件列表发送和回复格式研究
    FastCopy包含和排除文件夹处理
    Linux解压命令(tar)
    Linux下的删除命令
    分区还原工具(DiskGenius)
    树莓派利用PuTTY进行远程登录
    树莓派下载地址及一些常用工具
    树莓派开机黑屏问题解决
    Jenkins从2.x新建Job时多了一个文件夹的功能(注意事项)
    Jenkins的Publish Over FTP Plugin插件参数使用
  • 原文地址:https://www.cnblogs.com/zx0710/p/14083757.html
Copyright © 2011-2022 走看看