【动态规划】【最长上升子序列】【贪心】bzoj1046 [HAOI2007]上升序列

nlogn求出最长上升子序列长度。

对每次询问,贪心地回答。设输入为x。当前数a[i]可能成为答案序列中的第k个,则若 f[i]>=x-k && a[i]>ans[k-1] 即可。

f[i]表示以a[i]开头的最长上升子序列长度。

但这个东西难以统计。so 我们将原序列反序,求f[i] 表示以 a[i]为结尾的最长下降子序列长度即可。最后再将f、a reverse一下。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int a[10001],n,m,en=1,len,last;
 5 int b[10001];//b[i]:将a翻转后,长度为i的最长下降子序列的末尾
 6 int c[10001];//c[i]:将a翻转后,以a[i]开头的最长下降子序列的长度
 7 bool cmp(const int &a,const int &b){return a>b;}
 8 int main()
 9 {
10     scanf("%d",&n);
11     for(int i=1;i<=n;i++) scanf("%d",&a[n-i+1]);
12     scanf("%d",&m);
13     b[1]=a[1]; c[1]=1;
14     for(int i=2;i<=n;i++)
15       {
16           int *p=lower_bound(b+1,b+en+1,a[i],cmp);
17           if(!(*p)) ++en;
18           *p=a[i];
19           c[i]=p-b;
20       }
21     for(int i=1;i<=(n>>1);i++) swap(c[i],c[n-i+1]),swap(a[i],a[n-i+1]);
22     for(int i=1;i<=m;i++)
23       {
24           scanf("%d",&len);
25           if(len>en)
26             {
27                 puts("Impossible");
28                 continue;
29             } last=0;
30           for(int j=1;j<=n;++j)
31             if(c[j]>=len&&a[j]>last)
32               {
33                 printf("%d",last=a[j]);
34                 if(!(--len))
35                   {
36                     puts("");
37                     break;
38                   } putchar(' ');
39               }
40       }
41     return 0;
42 }
posted @ 2014-11-22 20:18  AutSky_JadeK  阅读(221)  评论(2编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト