1. 程式人生 > 實用技巧 >CF568E. Longest Increasing Subsequence

CF568E. Longest Increasing Subsequence

題目大意

題解

從各種意義上來說都很離譜的題

看到k<=1e3,一眼k^2logn,結果是(n+m)k,1.5s兩億

並且還是上升子序列,所以用nlogn的方法在不確定時維護指標掃一遍轉移即可

關於如果是單調不減的思考(口胡):

在維護的時候維護填入的相同數個數,轉移時考慮還要加上個數的限制,陣列中一段相同數的出現次數應該是前面一段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("\n");
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}