题目链接: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/单调队列)的更多相关文章

  1. [NOIP2010初赛]烽火传递+单调队列详细整理

    P1313 [NOIP2010初赛]烽火传递 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述   烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上 ...

  2. 【BZOJ 1758】【WC 2010】重建计划 分数规划+点分治+单调队列

    一开始看到$\frac{\sum_{}}{\sum_{}}$就想到了01分数规划但最终还是看了题解 二分完后的点分治,只需要维护一个由之前处理过的子树得出的$tb数组$,然后根据遍历每个当前的子树上的 ...

  3. 树形DP+RMQ+单调队列(Bob’s Race HDU4123)

    题意:有n个房子,这些房子被n-1条道路连接,有一些运动员从一个房子为起点尽可能跑最远的距离且不能通过一条道路超过两次,这些运行员不能选择同样的起点,这些运动员跑的最远距离和最近距离的差值不能超过Q, ...

  4. HDU 4123(树的直径+单调队列)

    Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  5. 【POJ 3162】 Walking Race (树形DP-求树上最长路径问题,+单调队列)

    Walking Race   Description flymouse's sister wc is very capable at sports and her favorite event is ...

  6. 两种解法-树形dp+二分+单调队列(或RMQ)-hdu-4123-Bob’s Race

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4123 题目大意: 给一棵树,n个节点,每条边有个权值,从每个点i出发有个不经过自己走过的点的最远距离 ...

  7. HDU 4123 Bob’s Race 树的直径+单调队列

    题意: 给定n个点的带边权树Q个询问. 以下n-1行给出树 以下Q行每行一个数字表示询问. 首先求出dp[N] :dp[i]表示i点距离树上最远点的距离 询问u, 表示求出 dp 数组中最长的连续序列 ...

  8. 1023: [SHOI2008]cactus仙人掌图(DP+单调队列优化)

    这道题吗= =首先解决了我多年以来对仙人掌图的疑问,原来这种高大上的东西原来是这个啊= = 然后,看到这种题,首先必须的就是缩点= = 缩点完之后呢,变成在树上找最长路了= =直接树形dp了 那么那些 ...

  9. [BZOJ 2500]幸福的道路 树形dp+单调队列+二分答案

    考试的时候打了个树链剖分,而且还审错题了,以为是每天找所有点的最长路,原来是每天起点的树上最长路径再搞事情.. 先用dfs处理出来每个节点以他为根的子树的最长链和次长链.(后面会用到) 然后用类似dp ...

随机推荐

  1. x86 寻址学习

    x86 寻址方式众多,什么直接寻址.间接寻址.基址寻址.基址变址寻址等等让人眼花缭乱,而 AT&T 语法对内存寻址方式做了一个很好的统一,其格式为 section:displacement(b ...

  2. Java for LeetCode 107 Binary Tree Level Order Traversal II

    Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left ...

  3. history显示历史操作记录,并显示操作时间

    在查看历史的操作记录有两种方式1.在用户的目录下的.bash_history文件中[root@node1 ~]# vi ~/.bash_history rebootvi /etc/sysconfig/ ...

  4. java与js互调 调用系统播放器

    <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=&q ...

  5. i=i+2 与i+=2

    i=i+2 比 i+=2多了一次对变量 i 的运算.后者效率高

  6. js/jq 动态添加的元素不能触发绑定事件解决方案

    <!-- Copyright 2017-10-27, Jachin QQ: 381558301 Email: 381558301@qq.com 请看看你们的版本并对号入座: jquery1.6版 ...

  7. centos 7 部署 mysql 报错记录

    1. Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY 这是由于yum安装了旧版本的GPG keys造成的,解决办法就是 引用  rpm --i ...

  8. CSS3悬停特效合集Hover.css

    CSS3悬停特效合集Hover.css是一款特效丰富,支持2D变化特效.边框特效.阴影特效等: 使用简单,可直接复制相关特效代码,快速应用到元素上. 源码地址:http://www.huiyi8.co ...

  9. 阿里大于短信服务_异常_01_InvalidTimeStamp.Expired

    一.异常信息 dm.aliyuncs.com InvalidTimeStamp.Expired Specified time stamp or date value is expired. 二.异常原 ...

  10. Workerman安装流程

    第一步检测安装环境 curl -Ss http://www.workerman.net/check.php | php 操作结果显示 报错了  需要找到php.ini文件 解决办法如下: 打开 php ...