zoukankan      html  css  js  c++  java
  • CF568E Longest Increasing Subsequence

    Link
    求LIS有一个贪心+二分的做法:维护(F_i)表示长度为(i)的LIS的最小末尾。
    对于(a_i=-1)的位置,我们可以先把(b)排序之后利用双指针重新计算(F),时间复杂度为(O(nlog n+(n+m)k))
    现在还需要输出方案,一个普遍的做法是记录每个元素的前驱,但是对于(a_i=-1)的部分开不下这么大的空间。
    实际上可以只记录(a_i e-1)的前驱,(a_i=-1)的位置只需要在求LIS的时候预处理相关信息即可。
    从后往前还原答案时,对于LIS中的(a_i=-1)的位置,贪心地选择最大的合法的数即可。

    #include<cctype>
    #include<cstdio>
    #include<utility>
    #include<algorithm>
    using pi=std::pair<int,int>;
    const int N=100007;
    int a[N],b[N],pre1[N],pre2[N],vis[N];pi f[N];
    int read(){int x=0,c=getchar(),f=1;while(isspace(c))c=getchar();if(c=='-')f=-1,c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return f*x;}
    int find(int x){return !~a[f[x].second]? pre2[x]:f[x].second;}
    int main()
    {
        int n,m,len=0,las=2e9;
        n=read();
        for(int i=1;i<=n;++i) a[i]=read();
        m=read();
        for(int i=1;i<=m;++i) b[i]=read();
        std::sort(b+1,b+m+1);
        for(int i=1;i<=n;++i)
    	if(~a[i])
    	{
    	    int l=1,r=len+1,mid;
    	    while(l<r) f[mid=(l+r)/2].first<a[i]? l=mid+1:r=mid;
    	    f[l]={a[i],i},pre2[l]=pre1[i]=find(l-1),len+=len<l;
    	}
    	else
    	{
    	    len+=b[m]>f[len].first;
    	    for(int j=m,k=len;j;f[k]={b[j--],i},pre2[k]=find(k-1)) for(;k>1&&f[k-1].first>=b[j];--k);
    	}
        for(int i=find(len),j=n,k=m;;las=a[i],i=pre1[i])
        {
    	for(;j>i;--j) if(!~a[j]) {for(;b[k]>=las;--k);if(k&&b[k]>a[i])las=a[j]=b[k],vis[k--]=1;}
    	if(!i) break;
        }
        for(int i=1,k=1;i<=n;++i) if(!~a[i]) {for(;k<=m&&vis[k];++k);a[i]=b[k++];}
        for(int i=1;i<=n;++i) printf("%d ",a[i]);
    }
    
  • 相关阅读:
    10-JavaScript 条件语句
    9-JavaScript 比较
    8-JavaScript 运算符
    6-JavaScript 事件
    Sum Problem 重定向文件的使用
    Calculate A + B.
    Vue中computed的本质及与methods的区别
    外部文件使用django的models
    DjangoURL反向解析
    字符串格式化的方式
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12857439.html
Copyright © 2011-2022 走看看