HDU-4521 小明系列问题——小明序列 间隔限制最长上升子序列
题意:给定一个长度为N的序列,现在要求给出一个最长的序列满足序列中的元素严格上升并且相邻两个数字的下标间隔要严格大于d。
分析:
1.线段树
由于给定的元素的取值范围为0-10^5,因此维护一棵线段树,其中[l, r]的信息表示处理完前k个数时,序列最大元素落在[l, r]区间最长上升子序列的长度。从前往后处理给定的数组,处理到第 i 号元素时,更新第 i - d 号元素,这样就能够保证最长上升的序列间隔大于d,更新是需要更新到叶子节点的,但这里更新是单点更新,每次更新的位置是该元素的值,信息就是到该点的最长上升长度。
其实仔细分析可以发现这个解法其实是经典的O(n^2)的算法的改进,那个算法需要遍历之前的更新信息比较相对大小,因此也不能简单的维护前缀最值,而线段树由于节点是值信息,查询的时候就不要去检验之前大小关系,加之线段树有能够动态区间求解各种信息,时间复杂度就这么被降下来了。当然如果取值范围较大,只要N不大还能够离散化。
- #include <cstdlib>
- #include <cstring>
- #include <cstdio>
- #include <algorithm>
- #define lch (p<<1)
- #define rch (p<<1|1)
- using namespace std;
- const int N = ;
- int n, d;
- int seq[N];
- int alen[N];
- struct Node {
- int l, r;
- int len;
- }e[N*];
- void build(int p, int l, int r) {
- e[p].l = l, e[p].r = r, e[p].len = ;
- if (l != r) {
- int mid = (l + r) >> ;
- build(lch, l, mid), build(rch, mid+, r);
- }
- }
- void push_up(int p) {
- e[p].len = max(e[lch].len, e[rch].len);
- }
- void modify(int p, int x, int val) {
- if (e[p].l == e[p].r) e[p].len = max(e[p].len, val);
- else {
- int mid = (e[p].l + e[p].r) >> ;
- if (x <= mid) modify(lch, x, val);
- else modify(rch, x, val);
- push_up(p);
- }
- }
- int query(int p, int l, int r) {
- if (e[p].l == l && e[p].r == r) return e[p].len;
- else {
- int mid = (e[p].l + e[p].r) >> ;
- if (r <= mid) return query(lch, l, r);
- else if (l > mid) return query(rch, l, r);
- else return max(query(lch, l, mid), query(rch, mid+, r));
- }
- }
- int main() {
- while (scanf("%d %d", &n, &d) != EOF) {
- build(, , ); // 建立0-10^5的线段树
- int ret = ;
- for (int i = ; i <= n; ++i) {
- scanf("%d", &seq[i]);
- if (seq[i] > ) ret = max(ret, alen[i]=query(, , seq[i]-)+);
- else ret = max(ret, alen[i] = );
- if (i-d>=) modify(, seq[i-d], alen[i-d]);
- }
- printf("%d\n", ret);
- }
- return ;
- }
2.经典O(nlogn)LIS变种
经典的算法在数组中保留都是下标节点比当前点小的节点,因为从前往后处理也因为经典的算法其实处理的是间隔d=0的特殊情况,那么稍微进行一下推广,当我们处理完第 i 个元素只是把第 i - d 号元素放到数组中,放入的位置就是以前求出来的最长上升子序列长度,当然放入的时候要比较一下是否需要替换。
- #include <cstdlib>
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #include <vector>
- using namespace std;
- const int N = ;
- int n, d;
- int seq[N];
- int alen[N];
- void solve() {
- vector<int>vt;
- vector<int>::iterator it;
- int ret = ;
- for (int i = ; i <= n; ++i) {
- it = lower_bound(vt.begin(), vt.end(), seq[i]);
- if (it == vt.end()) alen[i] = vt.size()+;
- else alen[i] = it-vt.begin()+;
- if (i-d >= ) {
- if (vt.size() == alen[i-d]-) vt.push_back(seq[i-d]);
- else if (vt[alen[i-d]-] > seq[i-d]) vt[alen[i-d]-] = seq[i-d];
- }
- ret = max(ret, alen[i]);
- }
- printf("%d\n", ret);
- }
- int main() {
- while (scanf("%d %d", &n, &d) != EOF) {
- for (int i = ; i <= n; ++i) {
- scanf("%d", &seq[i]);
- }
- solve();
- }
- return ;
- }
HDU-4521 小明系列问题——小明序列 间隔限制最长上升子序列的更多相关文章
- hdu 4521 小明系列问题——小明序列 线段树+二分
小明系列问题——小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Pro ...
- hdu 4521 小明系列问题——小明序列(线段树+DP或扩展成经典的LIS)
小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Tot ...
- 小明系列问题――小明序列(LIS)
小明系列问题――小明序列 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit ...
- hdu----(4521)小明系列问题——小明序列
小明系列问题——小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Tota ...
- 小明系列问题——小明序列(Lis 相距大于d的单调上升子序列)
小明系列问题——小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Tot ...
- 2018.07.08 hdu4521 小明系列问题——小明序列(线段树+简单dp)
小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Proble ...
- HDU 4521 小明系列问题——小明序列 (线段树 单点更新)
题目连接 Problem Description 大家都知道小明最喜欢研究跟序列有关的问题了,可是也就因为这样,小明几乎已经玩遍各种序列问题了.可怜的小明苦苦地在各大网站上寻找着新的序列问题,可是找来 ...
- hdu 4521 小明系列问题——小明序列(线段树 or DP)
题目链接:hdu 4521 本是 dp 的变形,却能用线段树,感觉好强大. 由于 n 有 10^5,用普通的 dp,算法时间复杂度为 O(n2),肯定会超时.所以用线段树进行优化.线段树维护的是区间内 ...
- HDU 4521 小明系列问题——小明序列 (线段树维护DP)
题目地址:HDU 4521 基本思路是DP.找前面数的最大值时能够用线段树来维护节省时间. 因为间隔要大于d. 所以能够用一个队列来延迟更新,来保证每次询问到的都是d个之前的. 代码例如以下: #in ...
随机推荐
- Java中如何在另一个类里面使用运行类中的对象,举例说明了一下。
package 计时器; import java.util.Timer; import java.util.TimerTask; /* * 主要是想在另一个类里面,使用该类的对象,如何使用呢?如何传递 ...
- Asp.Net Web Api 2 实现多文件打包并下载文件示例源码_转
一篇关于Asp.Net Web Api下载文件的文章,之前我也写过类似的文章,请见:<ASP.NET(C#) Web Api通过文件流下载文件到本地实例>本文以这篇文章的基础,提供了Byt ...
- Axure简介
Axure RP(Rapid Prototyping快速原型) 是美国公司Axure Software Solution公司旗舰产品,是一个专业的快速原型设计工具,让负责定义需求和规格.设计功能和界面 ...
- jqGrid中选择的行的数据[转]
如何获取jqGrid中选择的行的数据? 下面可以获取选择一行的id,如果你选择多行,那下面的id是最后选择的行的id: var id=$(‘#gridTable’).jqGrid(‘getGridPa ...
- Objective-C占位符
%@ 对象 %d, %i 整数 %li 长整型 %u 无符号整形 %f 浮点/双字 %x, %X 二进制整数 %o 八进制整数 %zu size_t %p 指针 %e 浮点/ 双字 (科学计算) (d ...
- get/post方式调用http接口
http://www.cnblogs.com/java-pan/tag/HTTP/ http://www.cnblogs.com/snoopylovefiona/p/4730242.html(可做参考 ...
- SpringMVC 接收复杂对象
要发送的数据为:String topicId,String topicName,String summarize,List<ModuleParam> parentList 前端页面ajax ...
- poj-3259-wormholes-spfa-判负环
题意:N个顶点, M条双向边, W条权值为负的单向边.求是否存在负环. 思路:首先你要懂bellman-ford或spfa..这是基础的spfa判断是否存在负环的题,存在负环的节点会重复入队(因为最短 ...
- Pots 分类: 搜索 POJ 2015-08-09 18:38 3人阅读 评论(0) 收藏
Pots Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11885 Accepted: 5025 Special Judge D ...
- Binary Tree 分类: POJ 2015-06-12 20:34 17人阅读 评论(0) 收藏
Binary Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6355 Accepted: 2922 Descr ...