和字典序有关的题型啊。

Description

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

Input

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

Output

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

Sample Input

  6
  3 4 1 2 3 6
  3
  6
  4
  5

Sample Output

  Impossible
  1 2 3 6
  Impossible

HINT

  N<=10000,M<=1000。

Solution

  看到字典序和上升子序列DP,小C想起了APIO2009的那道convention。

  (不要吐槽小C的做题顺序)

  既然要取字典序最小的,那肯定就是从小的取起,能取就取。

  那什么情况算是能取的呢?

  设要取的上升序列长度为len,已经取了x个数,且最后一个数大小为last。

  设我们当前要取的数的位置为i,数的大小为a[i],以这个位置开头的最长上升子序列长度为d[i]。

  那么如果a[i]>last且d[i]+x>=len那么i这个位置的数就能取,也就是必须取。

  我们来分析为什么这两个条件可以决定这个数取不取。

    a[i]>last是上升序列的必要条件,我们已经满足了last必须取,且上一个取last一定能构造出答案,所以从字典序最小的角度来说,我们不能用a[i]来替换last。

    d[i]+x>=len则是能构造出长度为len的答案的充分条件,因为d[i]满足二分性,如果d[i]>=len-x,那么一定存在一个以a[i]开头长度为len-x的上升序列接在last后面,从字典序最小的角度来说,我们取它显然最优。

  剩下就是求d[i]了嘛。求最长上升子序列谁不会啊?

  其实是正常的字典序也好,还是这题的逗比字典序也好,用以上的思路都是可以做的。

  时间复杂度O(nlogn+n*m)。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define MN 10005
#define MM 1005
using namespace std;
struct meg{int val,pos;}b[MM];
int f[MN],a[MN],p[MN],lb[MM],ans[MM][MN],t[MN<<];
int nin,n,m,MQ; inline int read()
{
int n=,f=; char c=getchar();
while (c<'' || c>'') {if(c=='-')f=-; c=getchar();}
while (c>='' && c<='') {n=n*+c-''; c=getchar();}
return n*f;
} void dfs(int depth,int x,int L,int R,int ps)
{
register int i,j,dx,mx=L-;
for (i=x;i<=n;++i)
{
if (a[i]<=ps) continue;
dx=lower_bound(lb+,lb+m+,f[i]+depth)-lb-;
if (dx>mx)
{
for (j=mx+;j<=dx;++j) ans[b[j].pos][depth]=a[i],mx=lb[j]==depth?j:mx;
if (dx>mx) {dfs(depth+,i+,mx+,dx,a[i]); mx=dx;}
if (mx==R) break;
}
}
} inline void getad(int x,int z) {for (x+=MQ;x&&z>t[x];x>>=) t[x]=z;}
inline int getmx(int L,int R)
{
if (L>R) return ;
register int lt=;
for (L+=MQ,R+=MQ;L<=R;L>>=,R>>=)
{
if ( L&) lt=max(lt,t[L++]);
if (~R&) lt=max(lt,t[R--]);
}
return lt;
}
bool cmp(const meg& a,const meg& b) {return a.val<b.val;} int main()
{
register int i,j;
n=read();
for (i=;i<=n;++i) a[i]=p[i]=read();
sort(p+,p+n+);
nin=unique(p+,p+n+)-p-;
for (i=;i<=n;++i) a[i]=lower_bound(p+,p+nin+,a[i])-p;
for (MQ=;MQ<nin;MQ<<=); --MQ;
for (i=n;i;--i) f[i]=getmx(a[i]+,nin)+,getad(a[i],f[i]);
m=read();
for (i=;i<=m;++i) b[i].val=read(),b[i].pos=i;
sort(b+,b+m+,cmp);
for (i=;i<=m;++i) lb[i]=b[i].val;
dfs(,,,m,);
for (i=;i<=m;++i)
{
if (!ans[i][]) {puts("Impossible"); continue;}
printf("%d",p[ans[i][]]);
for (j=;ans[i][j];++j) printf(" %d",p[ans[i][j]]); puts("");
}
}

Last Word

  不知道为什么突然想把询问排序然后一起做想降低常数,不过常数好像更大了233。

  因为看错字典序的缘故,小C的代码画风有点崩坏……(其实本来就很崩)

[BZOJ]1046 上升序列(HAOI2007)的更多相关文章

  1. BZOJ 1046 上升序列

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

  2. BZOJ 1046 上升序列(LIS变形)

    要保证长度为L的序列下标字典序最小,当然要尽量选前面的数. 如何判断前面的数是否满足条件?,只需要知道这个数开头的递增序列的最长长度是多少,如果不小于L,那么必然可以加入这个数.还需判断一下它是否大于 ...

  3. 【BZOJ】【1046】【HAOI2007】上升序列

    DP+贪心 啊……其实是个水题,想的复杂了 令f[i]表示以 i 为起始位置的最长上升子序列的长度,那么对于一个询问x,我们可以贪心地从前往后扫,如果f[i]>=x && a[i ...

  4. [BZOJ 1046] [HAOI2007] 上升序列 【DP】

    题目链接:BZOJ - 1046 题目分析 先倒着做最长下降子序列,求出 f[i],即以 i 为起点向后的最长上升子序列长度. 注意题目要求的是 xi 的字典序最小,不是数值! 如果输入的 l 大于最 ...

  5. BZOJ 1046 最长不降子序列(nlogn)

    nlogn的做法就是记录了在这之前每个长度的序列的最后一项的位置,这个位置是该长度下最后一个数最小的位置.显然能够达到最优. BZOJ 1046中里要按照字典序输出序列,按照坐标的字典序,那么我萌可以 ...

  6. [BZOJ 4350]括号序列再战猪猪侠 题解(区间DP)

    [BZOJ 4350]括号序列再战猪猪侠 Description 括号序列与猪猪侠又大战了起来. 众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号 序列S合法,当且仅当: 1.( )是一个 ...

  7. (WAWAWAWAWAWA) BZOJ 1858: [Scoi2010]序列操作

    二次联通门 : BZOJ 1858: [Scoi2010]序列操作 /* BZOJ 1858: [Scoi2010]序列操作 已经... 没有什么好怕的的了... 16K的代码... 调个MMP啊.. ...

  8. BZOJ 1046: [HAOI2007]上升序列 LIS -dp

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

  9. 【BZOJ 1046】 1046: [HAOI2007]上升序列

    1046: [HAOI2007]上升序列 Description 对于一个给定的S={a1,a2,a3,-,an},若有P={ax1,ax2,ax3,-,axm},满足(x1 < x2 < ...

随机推荐

  1. java关于for循环。

    众所周知,JAVA中for循环的基本格式为: for(初始化表达式:布尔表达式:循环后更新表达式){循环体} 举个例子来说可以写成 (1)for (int x=1;x<10;x++){ Syst ...

  2. 织梦cms/dedecms清理冗余废弃未引用图片方法

    原理描述: 在原有织梦后台菜单中增加"清理冗余图片按钮",实现清理冗余图片的功能. 操作步骤: 1. 打开后台dede\sys_sql_query.php代码 在该文件中搜索如下代 ...

  3. JAVA_SE基础——40.super关键字

    只要this关键字掌握了,super关键字不在话下,因为他们原理都差不多的.. this&super 什么是this,this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针 ...

  4. php的控制器链

    控制器之间协同工作就形成了控制器链· 比如在一个控制器的方法中,创建另外一个·控制器,创建对象,然后调用第二个控制器方法,那么在第一个控制器分配给视图的变量,在 第二个控制器的方法中对应的视图也是可以 ...

  5. 第一章 IDEA的使用

    第一章   IDEA的使用 1.为什么要使用idea 最智能的IDE IDEA相对于eclipse来说最大的优点就是它比eclipse聪明.聪明到什么程度呢?我们先来看几个简单的例子. A.智能提示重 ...

  6. Python内置函数(27)——range

    英文文档: range(stop) range(start, stop[, step]) Rather than being a function, range is actually an immu ...

  7. maven编译时出现读取XXX时出错invalid LOC header (bad signature)

    问题原因 该包没有下载正确. 解决办法 找到该包的目录,删除该包重新下载即可. 重新下载后用maven test一下,红叉消失.

  8. 新概念英语(1-37)Making a bookcase

    What is Susan's favourite color ? A:You're working hard, Georage. What are you doing? B:I am making ...

  9. PHP 7.2 新功能介绍

    PHP 7.2 已經在 2017 年 11 月 30 日 正式發布 .這次發布包含新特性.功能,及優化,以讓我們寫出更好的代碼.在這篇文章裡,我將會介紹一些 PHP 7.2 最有趣的語言特性. 你可以 ...

  10. 基于 MySQL 的数据库实践(基本查询)

    首先根据准备工作中的操作导入大学模式,打开数据库连接后进入到 MySQL 的交互界面,再使用命令 use db-book; 切换到 db-book 数据库. 单关系查询 SQL 查询的基本结构由三个子 ...