[BZOJ1046][HAOI2007]上升序列 DP+贪心
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1046
我们先求出对于每一个数字作为开头的LCS的长度f[i],最长的f[i]为mxlen。
对于每一个询问,我们选取答案,从第1个开始选。假设当前已经选到了第x个答案,我们只需要一直往后面找到第一个f[k]且f[k]+x>mxlen,它就是第x+1个答案。
这样时间复杂度就是$O(nm)$的,感觉玄学卡过……
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int INF=1<<30; 6 int inline readint(){ 7 int Num=0,Flag=1;char ch; 8 while((ch=getchar())<'0'||ch>'9') if(ch=='-') break; 9 if(ch=='-') Flag=-1; else Num=ch-'0'; 10 while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0'; 11 return Num*Flag; 12 } 13 int a[10010],n; 14 int sta[10010],f[10010]; 15 int main(){ 16 n=readint(); 17 for(int i=1;i<=n;i++) a[i]=readint(); 18 int mxlen=1; 19 sta[1]=-a[n]; 20 f[n]=1; 21 for(int i=n-1;i>=1;i--){ 22 int k=lower_bound(sta+1,sta+mxlen+1,-a[i])-sta; 23 f[i]=k; 24 sta[k]=-a[i]; 25 mxlen=max(mxlen,k); 26 } 27 int m=readint(); 28 for(int i=1;i<=m;i++){ 29 int l=readint(); 30 if(l>mxlen) puts("Impossible"); 31 else{ 32 int cnt=1,la=-INF; 33 for(int j=1;j<=n;j++){ 34 if(a[j]>la&&f[j]+cnt>l){ 35 cnt++; 36 la=a[j]; 37 if(cnt<=l) printf("%d ",a[j]); 38 else{ 39 printf("%d",a[j]); 40 break; 41 } 42 } 43 } 44 putchar('\n'); 45 } 46 } 47 return 0; 48 }