CF568E. Longest Increasing Subsequence

题目大意

题解

从各种意义上来说都很离谱的题

看到k<=1e3,一眼k^2logn,结果是(n+m)k,1.5s两亿

并且还是上升子序列,所以用nlogn的方法在不确定时维护指针扫一遍转移即可

转移的时候记下来上一个非-1的位置,最后贪心填

关于如果是单调不减的思考(口胡):

在维护的时候维护填入的相同数个数,转移时考虑还要加上个数的限制,数组中一段相同数的出现次数应该是前面一段0,之后一段单调+1序列,所以二分之后暴力修改至多k次

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
//#define file
using namespace std;

int a[100001],b[100001],c[100001],d[100001],f[100001],id[100001],pre[100001],n,m,i,j,k,l,r,mid,tot;

int main()
{
	#ifdef file
	freopen("CF568E.in","r",stdin);
	#endif
	
	scanf("%d",&n);
	fo(i,1,n) scanf("%d",&a[i]);
	scanf("%d",&m);
	fo(i,1,m) scanf("%d",&b[i]);
	sort(b+1,b+m+1);
	
	if (a[1]>-1) tot=1,f[1]=a[1],id[1]=1,pre[1]=0;
	else tot=1,f[1]=b[1],id[1]=0,pre[1]=0;
	fo(i,2,n)
	if (a[i]>-1)
	{
		l=1;r=tot;
		while (l<r)
		{
			mid=(l+r)/2;
			if (f[mid]<a[i])
			l=mid+1; else r=mid;
		}
		
		if (a[i]>f[tot]) f[++tot]=a[i],id[tot]=i,pre[i]=id[tot-1];
		else f[l]=a[i],id[l]=i,pre[i]=id[l-1];
	}
	else
	{
		if (b[m]>f[tot]) f[++tot]=b[m],id[tot]=id[tot-1];
		k=tot;
		fd(j,m,1)
		{
			while (k>1 && f[k-1]>=b[j]) --k;
			if (b[j]<f[k])
			f[k]=b[j],id[k]=id[k-1];
		}
	}
	
	for (i=id[tot]; i; i=pre[i]) c[i]=d[i]=a[i];
	if (!c[n]) c[n]=1000000001;
	fd(i,n-1,1) c[i]=(c[i]>0)?c[i]:c[i+1];
	fo(i,2,n) d[i]=(d[i]>0)?d[i]:d[i-1];
	j=1;
	fo(i,1,n)
	if (a[i]==-1)
	{
		while (j<=m && b[j]<=d[i]) ++j;
		if (j<=m && b[j]<c[i])
		{
			while (j<m && b[j]==b[j+1]) ++j;
			a[i]=b[j],b[j]=-1,++j;
		}
	}
	j=1;
	fo(i,1,n)
	if (a[i]==-1)
	{
		while (j<=m & b[j]==-1) ++j;
		a[i]=b[j],++j;
	}
	fo(i,1,n) printf("%d ",a[i]);
	printf("
");
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/gmh77/p/13658378.html