【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 < ...
随机推荐
- php敏感词过滤
在项目开发中发现有个同事在做敏感词过滤的时候用循环在判断,其实是不用这样做的,用php的数组函数和字符串函数即可实现 function filterNGWords($string) { $badwor ...
- C++求最小公倍数
题目内容:求两个正整数的最小公倍数. 输入描述:输入数据含有不多于50对的数据,每对数据由两个正整数(0<n1,n2<100000)组成. 输出描述:对于每组数据n1和n2,计算最小公倍数 ...
- 【转载】Android通过ksoap2调用.net(c#)的webservice
转载自:http://www.cnblogs.com/badtree/articles/3242842.html ■下载 ksoap2-android 包 去http://code.google.co ...
- 实习感悟——SQL语句
在这次实习中用到了很多SQL语句,下面就给大家分享分享: 1.group by 字面意思我们一看就知道groupby通过分组的意思,通过数据库某个字段的分组我们可以做什么?联系到生活中,我们给一组对象 ...
- IIS 配置错误解决方法集合
问题:405 - 不允许用于访问此页的 HTTP 谓词 解决:IIS处理程序映射中添加模块映射,模块选择:ServerSideIncludeModule,名称:SSINC-HTML
- EXCLE中快速插入图片
在excle中怎么快速插入图片呢,一张一张点实在比较麻烦 解决办法: <table><img src="D:\A.png" width="60" ...
- 编写可维护的JavaScript之简易模版
/* * 正则替换%s * @para arg1(text) 需要替换的模版 * @para arg2 替换第一处%s * @para arg3 替换第二处%s * 返回替换后的字符串 */ var ...
- C# 获取图片的EXIF 信息
关于 EXIF 信息的介绍. 1 EXIF,是英文Exchangeable Image File(可交换图像文件)的缩写.EXIF是一种图像文件格式,只是文件的后缀名为jpg.EXIF信息是由数码相 ...
- OC中类的扩展介绍
对OC类的扩展总结如下: 共有4个: 1.子类 subClass 作用:可以使用类的继承来增添父类的变量和方法. 写法:在.h文件中 @interface Student : Person 2.分类 ...
- simplexml_load_string获取xml节点里的属性值
http://stackoverflow.com/questions/14359658/get-xml-attribute-using-simplexml-load-string 问: I am us ...