51nod1153(dfs/单调队列)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1153
题意:中文题诶~
思路:一个比较简单的方法是dfs隐式图搜索,不过用单调队列会快一点
1.先说一下隐式图搜索吧:
假设所有元素都满足条件的话,那么B数组元素就是给出数组排序后的下标啦,我们看一下样例。
9, 10, 2, -1, 3, -5, 0, -3, 1, 12, 5, 8, -2, 6, 4 排序后为:
12, 10, 9, 8, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -5 我们可以把12, 10, 9的下标加入B数组,不过8不行,因为8在12的右边,不满足8和9之间是所有元素都小于9这个条件。。。其实我们可以通过找区间最大值来解决这个问题,我们一开始将区间[l, r]定为全集,12为最大值,不难发现只要我们选取了区间[l, r]中的最大值的话,那么接下来选择区间[l, r]中的任意元素加入B数组都是可行的。12将这个区间分为了两部分,我们可以将剩下要加入B的元素从第一个或者第二部分集合里面选取。注意在一种B集合选取方案中我们不能两部分集合元素都选取,因为分别取自两部分集合的元素之间必定会有12这个最大元素啦。。。
我们看下当前状态,我们已经选取了12这个元素,剩下的元素可以全部从9...1或者5...4两个集合中选取,答案就是这两种情况中最大的啦。。。
我们很容易发现接着从集合9...1或者5...4中选取元素和我们一开始的情形是一样的。。。那么我们只要不停的选取当前区间的最大元素,再递归处理其两个子区间就ok啦。。。
代码:
#include <iostream>
#define MAXN 50010
using namespace std; int a[MAXN];
const int inf=-; int dfs(int l, int r){
if(l==r){ //***注意边界情况有两种,可能我们上一层递归中的最大元素mid是l, 或者l后一个元素
return ;
}else if(l>r){
return ;
}
int gg=inf, mid=;
for(int i=l; i<=r; i++){
if(a[i]>gg){
gg=a[i];
mid=i;
}
}
return max(dfs(l, mid-), dfs(mid+, r))+; //***递归两个子区间,答案是较大的值
} int main(void){
ios::sync_with_stdio(false), cin.tie(), cout.tie();
int n;
cin >> n;
for(int i=; i<n; i++){
cin >> a[i];
}
int ans=dfs(, n-);
cout << ans << endl;
return ;
}
递归时最大元素是随机的,时间复杂度和快排差不多,O(nlogn)
2.单调队列
通过上面的描述我们最大每个最大值都会将一个区间分成两个子区间(可以为空),那么我们是不是可以通过顺序遍历每个区间最大元素来找到答案?
我们可以通过单调队列来处理,我们用结构体数组gg存储队列,gg[i].x, gg[i].num分别存储第i个元素的值和从上一个区间最大值元素开始到当前元素B可以的最大长度(为了得到区间最大值的左儿子区间元素个数)。
那么对于当前元素x有两种情况:
1. x大于当前单调队列队尾的元素,即其为上一个区间最大值到x这个区间的区间最大值,维护单调队列我们删除从队尾开始所有比x小的元素即删除x这个最大值的所有左儿子区间元素,并获取其左儿子区间的元素个数。当我们处理到全集最大元素时就能获得其向左拓展的情况下的最优解啦。。
2. 若x不大于当前队尾元素的话,即其为上一个区间最大值的右儿子元素,用右儿子数目加上当前队列里面的元素数目,处理到最后一个区间最大值时就能得到向右拓展的最优解啦。。
我们取两者中的较大值就是答案了。。
感觉这个算法其实就是对前面dfs的模拟的,虽然效率提高到了O(n),不过不是很好理解额。。。
代码:
#include <iostream>
#define MAXN 50010
using namespace std; struct node{ //***gg[i]存储第单调队列第i个元素的值和从上一个区间最大值元素到第i个元素B的最大长度
int x, num;
}gg[MAXN]; int main(void){
ios::sync_with_stdio(false), cin.tie(), cout.tie();
int n, x, index=, ans=;
cin >> n >> gg[].x;
gg[].num=;
n--;
while(n--){
cin >> x;
int cc=;
while(index>=&&x>gg[index].x){ //***若出现比当前队尾大的数,即队列里上一个最大元素后面的元素都是当前最大元素的左儿子区间,
cc=max(cc, gg[index].num);//***那么我们令cc为为其左儿子区间里面最大可能多的B元素个数,其实就是x的左儿子数目啦
index--; //***删除比x小的元素
}
index++; //***将x加入单调队列,下标+1
cc++; //***x的右儿子区间为可加入B数组元素数目为cc,再加入x元素本身
cc=max(cc, index+); //***index其实就是队里的元素个数加上队列里最后一个元素当前右儿子区间的数目
ans=max(ans, cc); //***更新ans
gg[index].x=x; //***更新单调队列元素
gg[index].num=cc;
}
cout << ans << endl;
return ;
}
51nod1153(dfs/单调队列)的更多相关文章
- [NOIP2010初赛]烽火传递+单调队列详细整理
P1313 [NOIP2010初赛]烽火传递 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上 ...
- 【BZOJ 1758】【WC 2010】重建计划 分数规划+点分治+单调队列
一开始看到$\frac{\sum_{}}{\sum_{}}$就想到了01分数规划但最终还是看了题解 二分完后的点分治,只需要维护一个由之前处理过的子树得出的$tb数组$,然后根据遍历每个当前的子树上的 ...
- 树形DP+RMQ+单调队列(Bob’s Race HDU4123)
题意:有n个房子,这些房子被n-1条道路连接,有一些运动员从一个房子为起点尽可能跑最远的距离且不能通过一条道路超过两次,这些运行员不能选择同样的起点,这些运动员跑的最远距离和最近距离的差值不能超过Q, ...
- HDU 4123(树的直径+单调队列)
Bob’s Race Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 【POJ 3162】 Walking Race (树形DP-求树上最长路径问题,+单调队列)
Walking Race Description flymouse's sister wc is very capable at sports and her favorite event is ...
- 两种解法-树形dp+二分+单调队列(或RMQ)-hdu-4123-Bob’s Race
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4123 题目大意: 给一棵树,n个节点,每条边有个权值,从每个点i出发有个不经过自己走过的点的最远距离 ...
- HDU 4123 Bob’s Race 树的直径+单调队列
题意: 给定n个点的带边权树Q个询问. 以下n-1行给出树 以下Q行每行一个数字表示询问. 首先求出dp[N] :dp[i]表示i点距离树上最远点的距离 询问u, 表示求出 dp 数组中最长的连续序列 ...
- 1023: [SHOI2008]cactus仙人掌图(DP+单调队列优化)
这道题吗= =首先解决了我多年以来对仙人掌图的疑问,原来这种高大上的东西原来是这个啊= = 然后,看到这种题,首先必须的就是缩点= = 缩点完之后呢,变成在树上找最长路了= =直接树形dp了 那么那些 ...
- [BZOJ 2500]幸福的道路 树形dp+单调队列+二分答案
考试的时候打了个树链剖分,而且还审错题了,以为是每天找所有点的最长路,原来是每天起点的树上最长路径再搞事情.. 先用dfs处理出来每个节点以他为根的子树的最长链和次长链.(后面会用到) 然后用类似dp ...
随机推荐
- OpenCV Machine Learning 之 正态贝叶斯分类器 (Normal Bayes Classifier)
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/zhjm07054115/article/details/27631913
- SAP-Function
[转]sap函数大全 ********SAP中常用函数 函数名 描述SD_VBAP_READ_WITH_VBELN 根据销售订单读取表vbap中的信息EDIT_LINES 把READ_TEXT返回的L ...
- CALL FUNCTION 'BAPI_PO_CREATE1' 相关报错
*&---------------------------------------------------------------------**& Report ZQJ06*&am ...
- Java基础教程:对象比较排序
Java基础教程:对象比较排序 转载请标明出处:http://blog.csdn.net/wangtaocsdn/article/details/71500500 有时候需要对对象列表或数组进行排序, ...
- Android系统文件目录
- GDB调试core文件(2)
使用gdb和core dump迅速定位段错误 关键字:gdb.段错误.core dump 一.什么是core dump core:内存.核心的意思: dump:抛出,扔出: core dump:前提: ...
- 《CSS权威指南(第三版)》---第六章 文本属性
本章主要的内容是: 1.文本缩进: text-indent.行内元素无法缩进,一般用左内边距或外边距来创造这种效果. 2.文本对齐:text-align .只应用于块状元素. 3.行高:一般line- ...
- 《avascript 高级程序设计(第三版)》 ---第二章 在HTML中使用Javascript
本章主要讲解了,怎么在HTML中使用: 1.<script src=""></script> 属性:defer="defer" 表示脚本 ...
- 高通MSM8255 GPS 调试分析&&Android系统之Broadcom GPS 移植【转】
本文转载自:http://blog.csdn.net/gabbzang/article/details/12063031 http://blog.csdn.NET/dwyane_zhang/artic ...
- POJ2774 Long Long Message —— 后缀数组 两字符串的最长公共子串
题目链接:https://vjudge.net/problem/POJ-2774 Long Long Message Time Limit: 4000MS Memory Limit: 131072 ...