【ShuDeOJ2210】上升序列

来源:互联网 发布:linux查看用户所属组 编辑:程序博客网 时间:2024/05/21 13:22

声明:这里提到的ShuDeOJ只是老师搬的训练用的OJ。


描述

给一个长度10^5的非负序列,序列中的0可以任意换成任何数字(包括负数),问最长严格上升子序列长度。

输入
第一行有一个数n代表序列长度

第二行有n个数字ai代表序列每个值是多少。

输出
一行一个数字代表答案

样例输入
7
2 0 2 1 2 0 5
样例输出
5
提示

30% n<=5000 100% n<=1e5 ai<=1e6


分析:其实是很明显的dp最长上升子序列的变式。观察到1e5的数据规模肯定不能用朴实的O(n^2)的算法了。需要改变一下,用d[i]长度为i的子序列末数字最小的。因为如果有这样一组序列 1 4 2 3 7,搜到4位置的时候最长是2,搜到2的时候最长也是2,但是d[2]就要从4更新为2了,因为4卡住了比4小的,2在能构成同样长的上升子序列的情况下,能够让后面更多的数加入这个序列,比如2后面的3可以进入序列,然而4就把3卡掉了,所以这样记录一定最优。此时d[3]=3;解决了时间复杂度后,就是0的问题了。其实0也很好解决,只需要看0是否是有用的。比如1 0 2 中的0是无帮助的,1 0 3中的0变为2后就有帮助了。意思是看0后面的数与前面的数相差的值是否能构成上升趋势即可,那不如把每个0后面的所有数-1,并把0去掉再存入。样例就变为了 2 1 0 1 3.【不好理解可以再多列几组试着感知一下


然而还有一个容易忽略的问题,就是前导0.

如果按照上述思想实现可得90分,还有10分应该就是这样卡掉了。比如输入 

0 0 0 0 0 0 0 0 

输出会是9,显然不对。

按lzy大佬传授的方法,只需要在序列前面加-INF 末尾加INF再将答案-2即可。因为负无穷和正无穷始终会被算入你的最长上升子序列中

我当时觉得好妙啊orz,这样就避免了前导0的情况


#include<bits/stdc++.h>using namespace std;#define N 100000#define INF 0x7fffffffint str[N+10],zero[N+10],d[N+10],lis[N+10];int n,k,flag=0,cnt=1,maxx=0,ans;void init(){str[1]=-INF; for(int i=1;i<=n;i++){scanf("%d",&k);if(k==0){flag++;continue;}str[++cnt]=k-flag;zero[cnt]=flag;}++cnt;str[cnt]=INF;return ;}int Lis(){int i,l,r,mid,len=1;d[1]=str[1];for(int i=2;i<=cnt;i++){l=1;r=len;if(d[len]<str[i]){len++;d[len]=str[i];continue;}while(l<=r)//用lower_bound也可以{mid=(l+r)/2;if(d[mid]<str[i])l=mid+1;elser=mid-1;}d[l]=str[i];}return len;}int main(){scanf("%d",&n);init();ans=Lis()+flag-2;printf("%d",ans);return 0;}


阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 蓝寇小黑瓶眼霜 兰寇小黑瓶眼部精华 寇字成语 寇振海 寇振海个人资料 章小蕙寇振海 寇振海妻子李婷去世 寇白门 寇组词和拼音 寇的组词有什么 寇绍恩 寇绍恩讲道 寇绍恩去世 寇绍恩什么时候去世的 寇绍恩牧师去世多少岁 寇绍恩牧师去世了吗 寇老西 寇老西片尾曲 寇老西演员表 贫而无怨难富而无骄易 贵不期骄 贵不召骄 胜而不骄败而不馁 斯为泰山而不骄 恃宠不骄枉为妃 落月沉香 斯为泰山而不骄什么意思 贵富临门 富丽 富丽华 富丽豪庭 富丽大厦 富丽什么什么四字词语 江门富丽宫288服务流程 玛纳斯富丽华酒店电话 富丽嘉园 富丽园自助餐 富丽堂什么四字成语 富丽达花园二手房 大连富丽庭生活广场 富丽金澜湾 富丽金澜湾是烂尾楼