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 ...
随机推荐
- Java AQS详解(转)
原文地址 一.概述 谈到并发,不得不谈ReentrantLock:而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer(AQS)! 类如其名,抽象的队列式的同 ...
- 7-3 堆栈模拟队列(25 point(s)) 【数据结构】
7-3 堆栈模拟队列(25 point(s)) 设已知有两个堆栈S1和S2,请用这两个堆栈模拟出一个队列Q. 所谓用堆栈模拟队列,实际上就是通过调用堆栈的下列操作函数: int IsFull(Stac ...
- 项目发布之后 总提示有一个.DLL找不到或不匹配
最近发布项目(.net,winform)总提示有一个.dll文件找不到或者不匹配 但是在本地调试是正常的 这个.dll,原来是从.net组件中引用到项目的,后来我将此.dll文件从网上下载,然后在项目 ...
- Buffer的数据存取
缓冲区 存放要读取的数据 缓冲区 和 通道 配合使用 一个用于特定基本数据类行的容器.有java.nio包定义的,所有缓冲区都是抽象类Buffer的子类. Java NIO中的Buffer主要用于与N ...
- html5--2.3新的布局元素(2)-article
html5--2.3新的布局元素(2)-article 学习要点 了解article元素的语义和用法 完成一个简单的实例 article元素(标签) 用于定义一个独立的内容区块,比如一篇文章,一篇博客 ...
- 分享知识-快乐自己:Hibernate框架常用API详解
1):Configuration配置对象 Configuration用于加载配置文件. 1): 调用configure()方法,加载src下的hibernate.cfg.xml文件 Configura ...
- IDEAL葵花宝典:java代码开发规范插件 checkstyle、visualVM、PMD 插件
前言: visualVM: 运行java程序的时候启动visualvm,方便查看jvm的情况 比如堆内存大小的分配:某个对象占用了多大的内存,jvm调优必备工具. checkstyle: CheckS ...
- POJ 2503 Babelfish(map,字典树,快排+二分,hash)
题意:先构造一个词典,然后输入外文单词,输出相应的英语单词. 这道题有4种方法可以做: 1.map 2.字典树 3.快排+二分 4.hash表 参考博客:[解题报告]POJ_2503 字典树,MAP ...
- swoole+nginx反向代理
nginx配置: server { listen 80; server_name www.swoole.com; root /data/wwwroot/www.swoole.com; location ...
- JQuery添加删除标签
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <script src= ...