bzoj5427最长上升子序列(贪心+LIS)

Posted quzhizhou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj5427最长上升子序列(贪心+LIS)相关的知识,希望对你有一定的参考价值。

  题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=5427

  因为noip,博客咕了好久,这几天集中填一下坑。

  这题我们可以假设往不确定的空位里填数,然后考虑一下如何尽可能让空位多被选上。我们发现,如果有一个空位没在最后的最长上升子序列里,那么可以贪心地去掉一个被选上的数再加上去。

  那么我们假定所有的空位都被选上。这样原序列就被划分成了许多段,而每一段内的在最长上升子序列里的数都必须与两边相差至少2(留一个数给空位)。那么我们可以把每一段数整体减去前面空位的数量(即每个数的数值减去前面没被确定的数的个数),然后直接跑一遍最长上升子序列,加上空位数量就行了。

  代码:

技术分享图片
#include<cstdio>
#include<set>
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){int tmp=0; char c=nc(),f=1; for(;c<0||9<c;c=nc())if(c==-)f=-1; for(;0<=c&&c<=9;c=nc())tmp=(tmp<<3)+(tmp<<1)+c-0; return tmp*f;}
set<int>st;
int n,k,delta=0;
int main()
{
    n=read();
    for(int i=1;i<=n;i++){
        char ch=nc();
        while(ch<A||Z<ch)ch=nc();
        if(ch==K){
            k=read();
            set<int>::iterator iter=st.lower_bound(k-delta);
            if(iter==st.end())st.insert(k-delta);
            else if(*iter+delta>k)st.erase(iter),st.insert(k-delta);
        }
        else{
            ++delta;
            st.insert(-1000000000-delta);
        }
    }
    printf("%d
",st.size());
}
bzoj5427

 

以上是关于bzoj5427最长上升子序列(贪心+LIS)的主要内容,如果未能解决你的问题,请参考以下文章

LIS 最长上升子序列问题(动态规划贪心+二分)

最长上升子序列LIS

HDU1257 最少拦截系统 —— 贪心 or LIS(最长上升子序列)

BZOJ3591: 最长上升子序列

[bzoj3173]最长上升子序列_非旋转Treap

最长上升子序列 (LIS) 详解+例题模板 (全)(转)