1. 程式人生 > >【LIS】BZOJ1046(HAOI2007)[上升序列]題解

【LIS】BZOJ1046(HAOI2007)[上升序列]題解

題目概述

給出 {an} ,求下標字典序最小的上升子序列。

解題報告

水題吧……先求出 fi 表示以 i 為起點的最長上升子序列,然後只需要先找出第一個 fans1>xans1 ,再找出 fans2>x1,aans2>aans1,ans2>ans1ans2 ,以此類推就可以了。

剛開始把下標字典序最小看成字典序最小,成功貢獻了一發WA。

示例程式

#include<cstdio>
using namespace
std; const int maxn=10000; int n,te,a[maxn+5],f[maxn+5],ans[maxn+5]; int main(){ freopen("program.in","r",stdin); freopen("program.out","w",stdout); for (int i=(scanf("%d",&n),1);i<=n;i++) scanf("%d",&a[i]); for (int i=n;i;i--) for (int j=(f[i]=1,i+1);j<=n;j++) if
(a[j]>a[i]&&f[j]+1>f[i]) f[i]=f[j]+1; for (scanf("%d",&te);te;te--){ int L,i,j;ans[0]=0; for (scanf("%d",&L),i=0;L;L--,i=j){ for (j=i+1;j<=n;j++) if (f[j]>=L&&a[j]>a[i]) break; if (j>n) break;ans[++ans[0
]]=j; } if (L) {puts("Impossible");continue;} for (int i=1;i<=ans[0];i++) {if (i>1) putchar(' ');printf("%d",a[ans[i]]);} putchar('\n'); } return 0; }