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
 
 
 
正解:DP+贪心

解题报告:

  其实挺水的却花了我半个多小时。

  显然先DP做最长上升子序列,然后做贪心。显然从前往后扫,每次扫到第一个发现长度大于要求长度,且当前值>last的就输出,然后长度--,last=当前值。这样贪心应该是正确的。

  我WA了两发,因为当长度变成0时应该及时跳出,而不是往后做。

  然后我还学了一下nlogn的最长上升子序列的DP,思想也很简单,就是从后往前做,然后维护每种长度当前的开始的结点的值最大值,对于每个i都二分查找出它之后可以接的最大长度。这显然是nlogn的。

  n^2 的做法:

 //It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#ifdef WIN32
#define OT "%I64d"
#else
#define OT "%lld"
#endif
using namespace std;
typedef long long LL;
const int MAXN = ;
const int inf = (<<);
int n,m,maxl;
int a[MAXN],f[MAXN]; inline int getint()
{
int w=,q=;
char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar();
if (c=='-') q=, c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar();
return q ? -w : w;
} inline void work(){
n=getint(); for(int i=;i<=n;i++) a[i]=getint(),f[i]=;
int len;
for(int i=n-;i>=;i--) {//事实上可以nlogn做最长上升子序列,记录每种长度的出现的最大的值,然后二分查找找到能够匹配的最大长度值
len=;
for(int j=i+;j<=n;j++) {
if(a[j]>a[i] && f[j]>=len) len=f[j];
}
f[i]=len+; maxl=max(f[i],maxl);
}
m=getint(); int x,last;
for(int o=;o<=m;o++) {//实际上这里不能直接输出,应该不断往后找可行解
if(o>) printf("\n");
x=getint(); last=-inf;
if(maxl<x) { printf("Impossible"); continue; }
for(int i=;i<=n;i++) {
if(f[i]>=x && a[i]>last) {
if(last!=-inf) printf(" ");
last=a[i]; x--;
printf("%d",a[i]);
if(!x) break;//及时跳出
}
}
}
} int main()
{
work();
return ;
}

  nlogn的做法:

  

 //It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#ifdef WIN32
#define OT "%I64d"
#else
#define OT "%lld"
#endif
using namespace std;
typedef long long LL;
const int MAXN = ;
const int inf = (<<);
int n,m;
int a[MAXN],f[MAXN],c[MAXN];//c[i]表示长度为i的开始结点的值的最大值
int maxl; inline int getint()
{
int w=,q=;
char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar();
if (c=='-') q=, c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar();
return q ? -w : w;
} inline int search(int x){//二分查找
int l=,r=maxl,mid; int pos;
while(l<=r) {
mid=(l+r)>>;
if(c[mid]>x) pos=mid,l=mid+;
else r=mid-;
}
return pos;
} inline void work(){
n=getint(); for(int i=;i<=n;i++) a[i]=getint();
int now; c[]=inf;
for(int i=n;i>=;i--) {//倒着查找
now=search(a[i]); f[i]=now+;
c[f[i]]=max(c[f[i]],a[i]);
maxl=max(maxl,f[i]);
}
m=getint(); int last;
for(int o=;o<=m;o++) {
if(o!=) printf("\n");
now=getint(); last=-inf;
if(now>maxl) { printf("Impossible"); continue; }
for(int i=;i<=n;i++){
if(f[i]>=now && a[i]>last) {
printf("%d",a[i]);
if(now!=) printf(" "); else break;//记得及时退出
now--; last=a[i];
}
}
}
} int main()
{
work();
return ;
}

BZOJ1046 [HAOI2007]上升序列的更多相关文章

  1. BZOJ1046 [HAOI2007]上升序列 【LIS + 字典序最小】

    1046: [HAOI2007]上升序列 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 5410  Solved: 1877 [Submit][St ...

  2. 2014.8.15模拟赛【公主的工作】&&bzoj1046[HAOI2007]上升序列

    bzoj题目是这样的 Description 对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm ...

  3. [BZOJ1046] [HAOI2007] 上升序列 (dp)

    Description 对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm)且( ax1 < ...

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

    nlogn求出最长上升子序列长度. 对每次询问,贪心地回答.设输入为x.当前数a[i]可能成为答案序列中的第k个,则若 f[i]>=x-k && a[i]>ans[k-1] ...

  5. BZOJ1046: [HAOI2007]上升序列(LIS)

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 5740  Solved: 2025[Submit][Status][Discuss] Descript ...

  6. bzoj1046 [HAOI2007]上升序列——LIS

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1046 倒序求最长下降子序列,则得到了每个点开始的最长上升子序列: 然后贪心输出即可. 代码如 ...

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

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1046 我们先求出对于每一个数字作为开头的LCS的长度f[i],最长的f[i]为mxlen. ...

  8. 【BZOJ1046】[HAOI2007]上升序列

    [BZOJ1046][HAOI2007]上升序列 题面 bzoj 洛谷 题解 \(dp\)完之后随便搞一下即可,注意不要看错题 代码 #include <iostream> #includ ...

  9. 【BZOJ-1046】上升序列 DP + 贪心

    1046: [HAOI2007]上升序列 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3723  Solved: 1271[Submit][Stat ...

随机推荐

  1. Doxygen Tool For Unity

    一.准备阶段 在之前的一系列文章中,我尝试了不同方法为Unity的C#生成脚本手册(帮助文档) 使用Doxygen生成C#帮助文档 为Unity项目生成文档(一)为Unity项目生成文档(二) 建议的 ...

  2. [cb] Unity Editor 添加右键菜单

    需求 为Unity的Editor窗口添加右键菜单 实现代码 // This example shows how to create a context menu inside a custom Edi ...

  3. LSB最低有效位隐写入门

    LSB也就是最低有效位 (Least Significant Bit) 被替换成传递的信息字节.对原图影响很小. 这题可以算是隐写工具[wbStego]的使用入门练习题吧. 第一步,告诉你工具是支持在 ...

  4. 26Spring_的注解实际应用_关键整理一下之前的注解

    写一个银行转账案例, 案例结构如下:

  5. Linux 下安装 jdk步骤:

    一:在安装自己下载的jdk之前,要先看看新安装的CentOS 6.4系统自带的jdk版本,如果存在最好是卸载掉,然后再安装自己下载的jdk版本,如何卸载linux系统自带的jdk网上有很多例子,相信大 ...

  6. Kinect for Windows SDK开发初体验(一)环境配置

    1.开发环境需求 (1).硬件需求 a.需要拥有双核,2.66GHz以上的CPU. b.显卡支持Microsoft DirectX 9.0c; c.2GB的内存 d.Kinect for Window ...

  7. Linux 网络编程八(epoll应用--大并发处理)

    //头文件 pub.h #ifndef _vsucess #define _vsucess #ifdef __cplusplus extern "C" { #endif //服务器 ...

  8. LUA 协程

    LUA协程和C#协程非常相似,功能与用法更强大.基础用法: coco = coroutine.create(function (a,b) print("resume args:". ...

  9. Boost_udp错误

      注意一点:当我们不同PC机间进行通信的时候,IP和端口号是不一样的.之前遇到的问题是,boost_system_error,这是因为我们在写程序的时候,发送和接收绑定了同一个端口,导致程序出错. ...

  10. 怎么样快速学习AngularJS?

    其实AngularJS的官方网站首页的几个例子已经很好的展示了AngularJS的一些特性,下面我就从几个例子一步一步的讲解AngularJS吸引人的东西并且实际项目中是怎么使用ng的. 首先还是从第 ...