前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BZOJ 1046: [HAOI2007]上升序列【贪心+二分状态+dp+递归】

BZOJ 1046: [HAOI2007]上升序列【贪心+二分状态+dp+递归】

作者头像
Angel_Kitty
发布2018-04-09 15:36:26
5360
发布2018-04-09 15:36:26
举报

1046: [HAOI2007]上升序列

Time Limit: 10 Sec  Memory Limit: 162 MB

Submit: 4987  Solved: 1732

[Submit][Status][Discuss]

Description

  对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm)且( ax1 < ax 2 < … < axm)。那么就称P为S的一个上升序列。如果有多个P满足条件,那么我们想求字典序最小的那个。任务给 出S序列,给出若干询问。对于第i个询问,求出长度为Li的上升序列,如有多个,求出字典序最小的那个(即首先 x1最小,如果不唯一,再看x2最小……),如果不存在长度为Li的上升序列,则打印Impossible.

Input

  第一行一个N,表示序列一共有N个元素第二行N个数,为a1,a2,…,an 第三行一个M,表示询问次数。下面接M 行每行一个数L,表示要询问长度为L的上升序列。N<=10000,M<=1000

Output

  对于每个询问,如果对应的序列存在,则输出,否则打印Impossible.

Sample Input

6 3 4 1 2 3 6 3 6 4 5

Sample Output

Impossible 1 2 3 6 Impossible

HINT

Source

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1046

分析:首先求出以每个数为开头上升序列长度,即倒着做最长下降子序列

然后,把字典序尽量小的放前面

即若要求的序列长度为x,如果以第一个数(字典序最小的数)开头的最长上升子序列大等于x,则将它放在答案第一个,第二个数开头小于x,则舍弃,第三个大于x-1,放答案第二个,以此类推!

下面给出AC代码:

代码语言:javascript
复制
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 inline int read()
 4 {
 5     int x=0,f=1;
 6     char ch=getchar();
 7     while(ch<'0'||ch>'9')
 8     {
 9         if(ch=='-')
10             f=-1;
11         ch=getchar();
12     }
13     while(ch>='0'&&ch<='9')
14     {
15         x=x*10+ch-'0';
16         ch=getchar();
17     }
18     return x*f;
19 }
20 int n,m,cnt;
21 const int N=100010;
22 int a[N],f[N],best[N];
23 inline void solve(int x)
24 {
25     int last=0;
26     for(int i=1;i<=n;i++)
27     {
28         if(f[i]>=x&&a[i]>last)
29         {
30             printf("%d",a[i]);
31             if(x!=1)
32                 printf(" ");
33             last=a[i];
34             if(!(--x))
35                 break;
36         }
37     }
38     printf("\n");
39 }
40 inline int find(int x)
41 {
42     int l=1,r=cnt,ans=0;
43     while(l<=r)
44     {
45         int mid=(l+r)/2;
46         if(best[mid]>x)
47             ans=mid,l=mid+1;
48         else
49             r=mid-1;
50     }
51     return ans;
52 }
53 inline void pre()
54 {
55     for(int i=n;i;i--)
56     {
57         int t=find(a[i]);
58         f[i]=t+1;
59         cnt=max(cnt,t+1);
60         if(best[t+1]<a[i])
61             best[t+1]=a[i];
62     }
63 }
64 int main()
65 {
66     n=read();
67     for(int i=1;i<=n;i++)
68         a[i]=read();
69     pre();
70     m=read();
71     for(int i=1;i<=m;i++)
72     {
73         int x=read();
74         if(x<=cnt)
75             solve(x);
76         else
77             printf("Impossible\n");
78     }
79     return 0;
80 }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-08-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1046: [HAOI2007]上升序列
  • Description
  • Input
  • Output
  • Sample Input
  • Sample Output
  • HINT
  • Source
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档