[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 }

 

posted @ 2017-09-04 21:31  halfrot  阅读(134)  评论(0编辑  收藏  举报