CF568E Longest Increasing Subsequence

先留个坑,输出方案的地方还得再想想

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;

const int maxn = 100010;
const int INF = 1e9+7;

int n,m,len,cnt;
int a[maxn],b[maxn],c[maxn];
int pre[maxn],from[maxn],tmp[maxn],v[maxn];

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }

int main(){
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    m=read();
    for(int i=1;i<=m;i++) b[i]=read();
    sort(b+1,b+1+m);
//    for(int i=1;i<=n;i++) c[i]=INF;
    
    len=0;
    for(int i=1;i<=n;i++){
        if(~a[i]){
            int p=lower_bound(c+1,c+1+len,a[i])-c;
            pre[i]=from[p-1];
            from[p]=i;
            c[p]=a[i];
            if(len<p) len=p;
            
        }else{
            int k=1;
            for(int j=1;j<=m;++j){
                while(k<=len&&c[k]<b[j]) ++k;
                tmp[j]=k;
            }
            if(len<k) len=k;
            for(int j=m;j;j--){
                c[tmp[j]]=b[j];
                from[tmp[j]]=from[tmp[j]-1];
            }
        }
    }
    cnt=0;
    for(int i=from[len];i;i=pre[i]){
        tmp[++cnt]=i;
    }
    tmp[0]=n+1;
    tmp[cnt+1]=0;
    
    a[n+1]=INF; b[m+1]=INF;
    for(int i=cnt+1;i;i--){ // 找到b中填到lis位置上的数 
        int last=a[tmp[i]];
        for(int j=tmp[i]+1;j<tmp[i-1];j++){
            if(!~a[j]){
                int k=upper_bound(b+1,b+1+m,last)-b;
                if(k>m||b[k]>=a[tmp[i-1]]) break;
                v[k]=1;
                last=a[j]=b[k];
            }
        }
    }
    
    for(int i=1,j=1;i<=n;i++){
        if(!~a[i]){
            while(j<m&&v[j]) ++j;
            a[i]=b[j];
            v[j]=1;
        }
    }
    for(int i=1;i<=n;i++){
        printf("%d ",a[i]);
    }printf("\n");
    
    return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/10421237.html