[BZOJ1046][HAOI2007]上升序列 DP+贪心

Posted halfrot

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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 }

 

以上是关于[BZOJ1046][HAOI2007]上升序列 DP+贪心的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1046[HAOI2007]上升序列

BZOJ1046 : [HAOI2007]上升序列

bzoj1046[HAOI2007]上升序列

Bzoj1046: [HAOI2007]上升序列

bzoj1046: [HAOI2007]上升序列

BZOJ 1046 [HAOI2007]上升序列