【hdu】4521 小明序列【LIS变种】【间隔至少为d】
题目链接:https://vjudge.net/contest/228455#problem/B
转载于:https://blog.csdn.net/a709743744/article/details/51765252
题目大意:
求最长上升子序列,其中子序列中相邻的两个数的下标差要超过k
解题分析:
子序列中相邻的两个数的下标要超过k,要想满足这个条件我们可以按下面的思路想:
首先nlogn的LIS是毫无疑问的,然后再这个算法中,我们每次二分找到当前数的位置,如果数组中的数比当前数大的话就更新数组
所以我们可以稍微改一下上述步骤,当我们二分计算当前数的位置时,只是把当前数应该在数组中的位置保存下来,当前只更新在i - k之前的那个数,
这样我们就可以保证每次二分查找时,数组中的所有数的下标都比当前的下标少至少k.
然而我还是没有弄懂,先记录着吧。
这是我的代码,用结构体,然后套用了一下LIS模板,不知道为什WA了
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 1e5 + ;
int n, d;
struct node
{
int val, ord;
}arr[MAXN],lis[MAXN]; int find(int l, int r, int key)
{
if (l == r)return l;
int mid = (l + r) >> ;
if (key>lis[mid].val)return find(mid + , r, key);
else return find(, mid, key);
} int main()
{
while (scanf("%d %d", &n, &d) != EOF){ //注意是下标之差大于d,而不是值之差大于d
memset(arr, , sizeof(arr));
for (int i = ; i <= n; i++) {
scanf("%d", &arr[i].val);
arr[i].ord = i;
}
int len = ;
for (int i = ; i <=n; i++){
if (i == )lis[++len] = arr[i];
else if (arr[i].val > lis[len].val) {
if ((arr[i].ord - lis[len].ord) > d)lis[++len] = arr[i];
}
else
{
int j = find(, len, arr[i].val);
if (j != len){
if (j == ){
if ((lis[].ord - arr[i].ord) > d)lis[j] = arr[i];
}
else{
if ((lis[j + ].ord - arr[i].ord) > d && (arr[i].ord - lis[j - ].ord) > d)
lis[j] = arr[i];
}
}
}
}
printf("%d\n", len);
}
return ;
}
AC的LIS解法
#include<iostream>
#include<cstring>
#include<cstdio>
#include <algorithm>
#define maxn 100005
using namespace std;
int a[maxn], b[maxn], p[maxn];
int n, d; int find(int p) //二分查找<=p的位置+1
{
int l, r, mid;
l = , r = n, mid = (l + r) >> ;
while (l <= r){
if (p>b[mid]) l = mid + ;
else if (p<b[mid]) r = mid - ;
else return mid;
mid = (l + r) >> ;
}
return l;
} int LIS(){
int i, j, ans = ;
for (i = ; i <= n; i++){
p[i] = find(a[i]); //p[i]存的是a[i]在上升数组中的位置
ans = max(ans, p[i]);
j = i - d;
if (j>) b[p[j]] = min(b[p[j]], a[j]);
}
return ans;
} int main()
{
int i, res;
while (cin >> n >> d){
for (i = ; i <= n; i++){
scanf("%d", &a[i]);
b[i] = maxn;
}
res = LIS();
printf("%d\n", res);
}
return ;
}
dp AC解法
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = + ;
int a[maxn], dp[maxn], g[maxn], n, k; int main()
{
while (~scanf("%d%d", &n, &k))
{
int ans = -;
memset(dp, , sizeof(dp));
memset(g, INF, sizeof(g));
for (int i = ; i <= n; i++)
scanf("%d", &a[i]);
for (int i = ; i <= n; i++)
{ //延迟p位更新 //为什么我感觉i>k+1以后还是连续的,下标并没有相差k啊???搞不懂
if (i - k - >) g[dp[i - k - ]] = min(a[i - k - ], g[dp[i - k - ]]); // i-p>1 是因为下标j范围为1<j<=m
dp[i] = lower_bound(g + , g + + n, a[i]) - g; //先记录下a[i]在g数组中的位置
ans = max(ans, dp[i]);
}
cout << ans << endl;
}
return ;
}
2018-05-17
【hdu】4521 小明序列【LIS变种】【间隔至少为d】的更多相关文章
- hdu4521 小明系列的问题——小明序列(LIS变种 (段树+单点更新解决方案))
链接: huangjing 题目:中文题目 思路: 1:这个题目假设去掉那个距离大于d的条件,那么必定是一个普通的LIS.可是加上那个条件后就变得复杂了.我用的线段树的解法. . .就是採用延迟更新的 ...
- hdu 4521 小明序列(线段树,DP思想)
题意: ①首先定义S为一个有序序列,S={ A1 , A2 , A3 , ... , An },n为元素个数 : ②然后定义Sub为S中取出的一个子序列,Sub={ Ai1 , Ai2 , Ai3 , ...
- hdu 4521 小明系列问题——小明序列(线段树+DP或扩展成经典的LIS)
小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Tot ...
- hdu 4521 小明系列问题——小明序列 线段树+二分
小明系列问题——小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Pro ...
- HDU 4521 小明系列问题——小明序列 (线段树 单点更新)
题目连接 Problem Description 大家都知道小明最喜欢研究跟序列有关的问题了,可是也就因为这样,小明几乎已经玩遍各种序列问题了.可怜的小明苦苦地在各大网站上寻找着新的序列问题,可是找来 ...
- 小明系列问题――小明序列(LIS)
小明系列问题――小明序列 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit ...
- 小明系列问题——小明序列(Lis 相距大于d的单调上升子序列)
小明系列问题——小明序列 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Tot ...
- hdu 4521 小明系列问题——小明序列(线段树 or DP)
题目链接:hdu 4521 本是 dp 的变形,却能用线段树,感觉好强大. 由于 n 有 10^5,用普通的 dp,算法时间复杂度为 O(n2),肯定会超时.所以用线段树进行优化.线段树维护的是区间内 ...
- HDU 4521 小明系列问题——小明序列 (线段树维护DP)
题目地址:HDU 4521 基本思路是DP.找前面数的最大值时能够用线段树来维护节省时间. 因为间隔要大于d. 所以能够用一个队列来延迟更新,来保证每次询问到的都是d个之前的. 代码例如以下: #in ...
随机推荐
- 《C#数据结构和算法》-排序
7.7 各种排序方法的比较与讨论 排序在计算机程序设计中非常重要,上面介绍的各种排序方法各有优缺点, 适用的场合也各不相同.在选择排序方法时应考虑的因素有: ( )待排序记录的数目 n 的大小: ( ...
- JavaScript学习 - 基础(三) - 运算符
js运算符 1.算数运算符 包括 加(+) .减-() .乘(*).除(/).余数(%) 减号 还可以表示为 负号 例如: -1,-3 加号 还可以用于字符串拼接 例如: 'a' + 'b' = 'a ...
- jquery菜单插件
原理很简单. 涉及到知识点: 1.jquery的position注意这里是jquery的position,不是css的position offset的概念 2.>的概念. 3..ulh>l ...
- vc++调用exe获取输出信息
目的 调用命令行程序,返回结果. 思路 把命令行结果输入到管道中,exe的输出信息都存在了strOutput这个变量里. 实现代码 CString strCmd = L"yara64.exe ...
- linux内核中链表代码分析---list.h头文件分析(一)【转】
转自:http://blog.chinaunix.net/uid-30254565-id-5637596.html linux内核中链表代码分析---list.h头文件分析(一) 16年2月27日17 ...
- oracle数据库自增主键重复
select max(t.id) from T_PLAT_ENUM_VALUE tdrop sequence T_PLAT_ENUM_VALUE;create sequence T_PLAT_ENUM ...
- Vue.js——循环(Java、JSTL标签库、数据库)
一.Vue.js循环 Vue.js循环要使用 v-for 指令. v-for 指令需要以 student in StudentList 形式的特殊语法使用, StudentList 是源数据数组并且s ...
- wordpress安装主题时提示无法创建目录
直接上解决办法: 找到wp-content文件夹(我的是在/home/wwwroot/default/wp-cotent) 首先给wp-content这个文件夹一个权限 chmod -R 775 wp ...
- css之margin
参考地址:http://www.imooc.com/learn/680 标准盒模型 元素尺寸 可视尺寸-clientWidth(标准)——就是上图中的border box包含的尺寸. 占据尺寸-out ...
- php-fpm 配置文件检测
用过 Nginx 的兄弟都知道,修改 Nginx 配置文件之后,可以使用 nginx -t 来检测配置文件是否有语法错误. 今天配置 opcache 的时候,发现 php-fpm 也可以检测 php- ...