• Codeforces 568E. Longest Increasing Subsequence 题解


    题目链接:E. Longest Increasing Subsequence

    题目大意:洛谷


    题解:首先如果要求的是最长上升子序列的长度是很简单的。

    因为是严格单调递增,所以每一个数在最长上升子序列中最多只会出现一次,所以对于(b)数组中的每一个数只能够取一次的限制可以不考虑,直接考虑传统的(O(nlog n))做法,那么对于正常的位置,正常地二分做,对于(-1)的位置,可以枚举当前位置选哪一个做。

    这一部分的时间复杂度是(O(nlog n+mk))的。

    接下来考虑还原方案。

    先考虑没有(-1)的情况。

    因为不是(O(n^2))的 DP,所以我们在转移(其实就是二分查找中的那一步,姑且称之为转移吧)的时候需要记录它的上一个位置,这样的话我们就可以倒推出来原序列的长度了。

    因为如果需要找最大值的位置的话比较麻烦,所以我们可以直接在序列末尾添加上一个( ext{Inf})

    接下来考虑(-1)应当怎么处理。

    直接在(b)数组中找到小于当前数的最大的数填进去就可以了。

    总时间复杂度(O(nlog n +mlog m +(n+m)k))

    代码:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    void read(int &a){
    	a=0;
    	int f=1;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-'){
    			f=-1;
    		}
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		a=(a<<1)+(a<<3)+(c^48);
    		c=getchar();
    	}
    	if(f==-1){
    		a=-a;
    	}
    }
    const int Maxn=100000;
    const int Maxk=1000;
    const int Inf=0x7f7f7f7f;
    int n,m;
    int a[Maxn+5],b[Maxn+5];
    bool vis[Maxn+5];
    int f[Maxn+5];
    int g[Maxn+5];
    int p[Maxn+5],pos[Maxn+5];
    int ans[Maxn+5];
    void get(int i,int k,int &x){
    	int tmp=lower_bound(b+1,b+1+m,k)-b-1;
    	vis[tmp]=1;
    	x=ans[i]=b[tmp];
    }
    int main(){
    	read(n);
    	for(int i=1;i<=n;i++){
    		read(a[i]);
    		f[i]=Inf;
    	}
    	n++;
    	a[n]=Inf;
    	f[n]=Inf;
    	read(m);
    	for(int i=1;i<=m;i++){
    		read(b[i]);
    	}
    	sort(b+1,b+1+m);
    	for(int i=1;i<=n;i++){
    		if(a[i]==-1){
    			for(int j=n,k=m;k>0;k--){
    				while(f[j]>=b[k]){
    					j--;
    				}
    				f[j+1]=b[k];
    				pos[j+1]=i;
    			}
    		}
    		else{
    			int j=lower_bound(f+1,f+1+n,a[i])-f-1;
    			g[i]=j+1;
    			p[i]=pos[j];
    			f[j+1]=a[i];
    			pos[j+1]=i;
    		}
    	}
    	{
    		int i=g[n],j=n,x=a[n];
    		while(i--){
    			if(a[j]!=-1){
    				if(a[p[j]]==-1){
    					get(p[j],a[j],x);
    				}
    				else{
    					x=a[p[j]];
    				}
    				j=p[j];
    			}
    			else{
    				bool flag=0;
    				for(int s=j-1;s>0;s--){
    					if(a[s]!=-1&&g[s]==i&&a[s]<x){
    						x=a[j=s];
    						flag=1;
    						break;
    					}
    				}
    				if(flag){
    					continue;
    				}
    				for(int s=j-1;s>0;s--){
    					if(a[s]==-1){
    						get(s,x,x);
    						j=s;
    						break;
    					}
    				}
    			}
    		}
    	}
    	for(int i=1,j=1;i<n;i++){
    		if(a[i]==-1){
    			if(ans[i]!=0){
    				a[i]=ans[i];
    				continue;
    			}
    			while(vis[j]){
    				j++;
    			}
    			vis[j]=1;
    			a[i]=b[j];
    		}
    	}
    	for(int i=1;i<n;i++){
    		printf("%d ",a[i]);
    	}
    	puts("");
    	return 0;
    }
    
    本博客欢迎转载,转载请注明文章出处作者
  • 相关阅读:
    poj3278 Catch That Cow
    poj2251 Dungeon Master
    poj1321 棋盘问题
    poj3083 Children of the Candy Cor
    jvm基础知识—垃圾回收机制
    jvm基础知识1
    java面试基础必备
    java soket通信总结 bio nio aio的区别和总结
    java scoket aIO 通信
    java scoket Blocking 阻塞IO socket通信四
  • 原文地址:https://www.cnblogs.com/withhope/p/13568057.html
Copyright © 2020-2023  润新知