DP+贪心


  啊……其实是个水题,想的复杂了

  令f[i]表示以 i 为起始位置的最长上升子序列的长度,那么对于一个询问x,我们可以贪心地从前往后扫,如果f[i]>=x && a[i]>last,则x--,last=a[i]

  保证$x_i$(下标)字典序最小……

 /**************************************************************
Problem: 1046
User: Tunix
Language: C++
Result: Accepted
Time:2116 ms
Memory:1428 kb
****************************************************************/ //BZOJ 1046
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=1e4+,INF=~0u>>;
typedef long long LL;
/******************tamplate*********************/
int n,m,a[N],b[N],len,f[N],ans[N];
int Find(int x){
int l=,r=len,mid,ans=len+;
while(l<=r){
mid=l+r>>;
if (b[mid]<=x) ans=mid,r=mid-;
else l=mid+;
}
return ans;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1046.in","r",stdin);
freopen("1046.out","w",stdout);
#endif
n=getint();
F(i,,n) a[i]=getint();
D(i,n,){
int x=Find(a[i]);
f[i]=x; b[x]=a[i];
if (x>len) len=x;
}
m=getint();int x;
while(m--){
x=getint();
if (len<x) {puts("Impossible");continue;}
int last=;
F(i,,n)
if (f[i]>=x && a[i]>last){
printf("%d",a[i]);
if (x!=) printf(" ");
last=a[i];
x--;
if (x==) break;
}
puts("");
}
return ;
}

P.S.一开始想成数值字典序最小了……如果是数值字典序的话也可做,方法类似?(以下内容与本题解法无关)

  预处理出来一张表,在这张表 f 中,f[i]里存的是最长上升子序列长度>=i 的数的下标,且满足这些数(即下标对应的数)是单调递减的。

  感觉说起来好怪……贴下代码吧

  就是满足下标单调增,但值单调减

 #include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=1e4+,INF=~0u>>;
typedef long long LL;
/******************tamplate*********************/
int n,a[N],best,ans[N];
vector<int>f[N];
vector<int>::iterator tmp;
int main(){
#ifndef ONLINE_JUDGE
freopen("1046.in","r",stdin);
freopen("1046.out","w",stdout);
#endif
n=getint();
F(i,,n) a[i]=getint();
f[].pb(); best=;
F(i,,n){
D(j,best,){
if (a[i]<a[f[j][f[j].size()-]] &&
a[f[j-][f[j-].size()-]]<a[i])
f[j].pb(i);
}
if (a[i]>a[f[best][f[best].size()-]]){
best++;
f[best].pb(i);
}
if (a[i]<a[f[][f[].size()-]]) f[].pb(i);
}
int m=getint(), x;
while(m--){
x=getint();
if (f[x].empty()){puts("Impossible");continue;}
ans[x]=f[x][f[x].size()-];
D(i,x-,){
tmp=lower_bound(f[i].begin(),f[i].end(),ans[x]);
tmp--;
ans[i]=*tmp;
}
F(i,,x) printf("%d ",a[ans[i]]);
puts("");
}
return ;
}

  也是贪心地去找最优解>_>

1046: [HAOI2007]上升序列

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2866  Solved: 960
[Submit][Status][Discuss]

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

Source

[Submit][Status][Discuss]

【BZOJ】【1046】【HAOI2007】上升序列的更多相关文章

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

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

  2. Bzoj 1046: [HAOI2007]上升序列 二分,递推

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

  3. BZOJ 1046: [HAOI2007]上升序列(LIS)

    题目挺坑的..但是不难.先反向做一次最长下降子序列.然后得到了d(i),以i为起点的最长上升子序列,接下来贪心,得到字典序最小. ----------------------------------- ...

  4. bzoj 1046 : [HAOI2007]上升序列 dp

    题目链接 1046: [HAOI2007]上升序列 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3620  Solved: 1236[Submit] ...

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

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

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

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

  7. bzoj 1046: [HAOI2007]上升序列

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

  8. bzoj 1046: [HAOI2007]上升序列【dp+二分】

    先从后到前做一个最长下降子序列的dp,记录f[i],我这里用的是二分(其实树状数组比较显然) 然后对于询问,超出最长上升子序列的直接输出:否则从前到后扫,f[i]>=x&&a[i ...

  9. BZOJ 1046 [HAOI2007]上升序列(LIS + 贪心)

    题意: m次询问,问下标最小字典序的长度为x的LIS是什么 n<=10000, m<=1000 思路: 先nlogn求出f[i]为以a[i]开头的LIS长度 然后贪心即可,复杂度nm 我们 ...

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

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

随机推荐

  1. c# 数据库操作学习

    一. 如何处理数据库连接 1. 数据库连接可以分为“物理连接”和“逻辑连接”(默认使用连接池的情况下Pooling=true): 物理连接:创建数据库连接时,默认会有一定数量的物理连接(默认Min P ...

  2. RequireJS和AMD规范

    目录 概述 define方法:定义模块 require方法:调用模块 AMD模式小结 配置require.js:config方法 插件 优化器r.js 参考链接 概述 RequireJS是一个工具库, ...

  3. SQL Server编程(04)基本语法

    一.定义变量 --简单赋值 declare @a int set @a=5 print @a   --使用select语句赋值 declare @user1 nvarchar(50) select @ ...

  4. Asp.net MVC4 Knockoutjs BootStrap Ace NinJect Jqgrid sqlserver2008

    Asp.net MVC4 Knockoutjs  BootStrap Ace NinJect  Jqgrid sqlserver2008

  5. .NET程序员爱上网站[整理]

    1.博客园(代码改变世界) http://www.cnblogs.com 2.开源中国社区(开源软件发现.使用和交流平台) http://www.oschina.net 3.CSDN(中国最大的IT社 ...

  6. 利用java读写Excel文件

    一.读取Excel文件内容 java 代码 public static String readExcel(File file){ StringBuffer sb = new StringBuffer( ...

  7. html中的框架

    1.总的代码 <frameset rows=20%,*> <frame src="top.html" /> <frameset cols=30%,*& ...

  8. javascript jquery each 影响 函数返回值

    实例如下: $(function(){ if(chkInput()){ alert('OK!') } }); function chkInput(){ var data = jsonData(略); ...

  9. Python开发【第一篇】Python基础之生成器和迭代器

    生成器和迭代器 1.生成器 一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator):如果函数中包含yield语法,那这个函数就会变成生成器: def func(): yield 1 ...

  10. Python脚本控制的WebDriver 常用操作 <九> 定位一组对象

    下面将使用WebDriver来模拟操作定位一组对象的操作 测试用例场景 从上一节的例子中可以看出,webdriver可以很方便的使用find_element方法来定位某个特定的对象,不过有时候我们却需 ...