题目大意:给定一个序列,求任意长度的上升子序列,要求字典序最小(这里的字典序是位置最小)
思路:用nlogn的做法求最长上升子序列,然后从头往后扫m遍,找后面的值大的同时f数组满足相应条件的值输出。求f数组的时候,用lower_bound wa了,但用upper_bound就ac了。。。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int a[10001]={0},d[10001]={0},f[10001]={0}; int main() { freopen("lis.in","r",stdin); freopen("lis.out","w",stdout); int i,j,n,m,len=0,now,x; scanf("%d",&n); for (i=1;i<=n;++i) scanf("%d",&a[i]); memset(d,128,sizeof(d)); d[n]=a[n];len=n;f[n]=1; for (i=n-1;i>=1;--i) { if (a[i]<d[len]) { d[--len]=a[i]; f[i]=n-len+1; } else { j=upper_bound(d+len+1,d+n+1,a[i])-d-1; if (d[j]!=a[i]) { d[j]=a[i];f[i]=n-j+1; } else f[i]=n-j+1; } } scanf("%d",&m);len=n-len+1; for (i=1;i<=m;++i) { scanf("%d",&x); if (x>len) printf("Impossible"); else { now=-2100000000; for (j=1;j<=n;++j) { if (f[j]>=x&&a[j]>now) { printf("%d",a[j]);--x;now=a[j]; if (!x) break; else printf(" "); } } } printf("\n"); } fclose(stdin); fclose(stdout); }
当得知n^2暴力能a的时候。。。
时间: 2024-10-08 13:28:56