【BZOJ】【1046】【HAOI2007】上升序列
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
3 4 1 2 3 6
3
6
4
5
Sample Output
1 2 3 6
Impossible
HINT
数据范围
N<=10000
M<=1000
Source
【BZOJ】【1046】【HAOI2007】上升序列的更多相关文章
- BZOJ 1046: [HAOI2007]上升序列 LIS -dp
1046: [HAOI2007]上升序列 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3438 Solved: 1171[Submit][Stat ...
- Bzoj 1046: [HAOI2007]上升序列 二分,递推
1046: [HAOI2007]上升序列 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3671 Solved: 1255[Submit][Stat ...
- BZOJ 1046: [HAOI2007]上升序列(LIS)
题目挺坑的..但是不难.先反向做一次最长下降子序列.然后得到了d(i),以i为起点的最长上升子序列,接下来贪心,得到字典序最小. ----------------------------------- ...
- bzoj 1046 : [HAOI2007]上升序列 dp
题目链接 1046: [HAOI2007]上升序列 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3620 Solved: 1236[Submit] ...
- BZOJ 1046: [HAOI2007]上升序列【贪心+二分状态+dp+递归】
1046: [HAOI2007]上升序列 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4987 Solved: 1732[Submit][Stat ...
- [BZOJ 1046] [HAOI2007] 上升序列 【DP】
题目链接:BZOJ - 1046 题目分析 先倒着做最长下降子序列,求出 f[i],即以 i 为起点向后的最长上升子序列长度. 注意题目要求的是 xi 的字典序最小,不是数值! 如果输入的 l 大于最 ...
- bzoj 1046: [HAOI2007]上升序列
Description 对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm)且( ax1 < ...
- bzoj 1046: [HAOI2007]上升序列【dp+二分】
先从后到前做一个最长下降子序列的dp,记录f[i],我这里用的是二分(其实树状数组比较显然) 然后对于询问,超出最长上升子序列的直接输出:否则从前到后扫,f[i]>=x&&a[i ...
- BZOJ 1046 [HAOI2007]上升序列(LIS + 贪心)
题意: m次询问,问下标最小字典序的长度为x的LIS是什么 n<=10000, m<=1000 思路: 先nlogn求出f[i]为以a[i]开头的LIS长度 然后贪心即可,复杂度nm 我们 ...
- 【BZOJ 1046】 1046: [HAOI2007]上升序列
1046: [HAOI2007]上升序列 Description 对于一个给定的S={a1,a2,a3,-,an},若有P={ax1,ax2,ax3,-,axm},满足(x1 < x2 < ...
随机推荐
- spring(spring boot)笔记
1.查看数据库连接:org.springframework.boot.autoconfigure.jdbc里的public DataSource dataSource() 方法.在这里打断点,可以查看 ...
- delphi构造&析构调用顺序
_ClassCreate ->Create ->AfterConstruction(->DoCreate / OnCreate) BeforeDestruction(->DoD ...
- Oracle存储过程学习备忘
之前的项目使用存储过程很少,但在实际的项目中,存储过程的使用是必不可少的. 存储过程是一组为了完成特定功能的SQL 语句 集,经编译后存储在数据库中:存储过程创建后,一次编译在程序中可以多次调用,对安 ...
- 03-树2 List Leaves
二叉树及其遍历 一遍AC,挺开心的hhh~ 简单讲下思路:叶子,顾名思义就是没有左右子树的结点.由于题目要求,叶子结点的输出顺序是从上往下,从左往右.所以用层序遍历法. 当然,这里先找到root树的根 ...
- python内建函数-数字相关
本篇对于数字有关的内置函数进行总结. 数字包括 int() , long() , float() , complex() ,这些函数都能够用来进行数值类型的转换.同时这些函数也接受字符串参数,返回字符 ...
- 《高性能javascript》读书笔记
1.每个<script>加载时都会阻塞其他文件(图片.音乐等)的同时加载,同时浏览器会在js代码执行时停止渲染Dom.所以为了减少界面加载的卡顿和空白发生,应尽力将js代码或者文件放在&l ...
- 关于Haproxy安装和配置:负载配置【haproxy.cfg】问题记录
1. 存放地址: more /etc/haproxy/haproxy.cfg ps -ef | grep haproxy 看看有没有haproxy的进程就是了 或者看看服务器的23306的端口有没有 ...
- Mybatis关于like的字符串模糊处理
其中通过"%"#{key}"%"来拼接语句 <sql id="select_where"> from cellphone c l ...
- Android动画解析--XML
动画类型 Android的animation由四种类型组成 XML中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画效果 translate 画面转换位置移动动画效果 rotate 画面 ...
- UIBezierPath 的使用介绍
使用UIBezierPath类可以创建基于矢量的路径.此类是Core Graphics框架关于path的一个封装.使用此类可以定义简单的形状,如椭圆或者矩形,或者有多个直线和曲线段组成的形状 ...