题目链接: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. OpenCV Machine Learning 之 正态贝叶斯分类器 (Normal Bayes Classifier)

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/zhjm07054115/article/details/27631913

  2. 利用framebuffer,命令行显示图片

    上代码 import fcntl import struct import mmap import contextlib import os import time import numpy as n ...

  3. Java for LeetCode 109 Convert Sorted List to Binary Search Tree

    Given a singly linked list where elements are sorted in ascending order, convert it to a height bala ...

  4. JSON中如何转义字符串中的双引号(转载)

    问: I'm trying to show double quotes but it shows one of the backslashes: "maingame": { &qu ...

  5. html的head中的常见元素

    <head></head>中有charset, title,link 操作系统默认的字符编码就是gbk. html的加强 (1)<a href="#" ...

  6. mysql七:视图、触发器、事务、存储过程、函数

    阅读目录 一 视图 二 触发器 三 事务 四 存储过程 五 函数 六 流程控制 一 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名 ...

  7. web项目的实质

    web项目的实质 web项目的实质其实也就是在用户发过来一个请求后,我们返回一个响应. 用户看到的页面就是我们响应中的响应体(里面是html代码). 所以,我们整个项目的所有操作都是围绕着怎么来写好这 ...

  8. hdu-5792 World is Exploding(容斥+树状数组)

    题目链接: World is Exploding Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Jav ...

  9. 构建基于虚拟用户的vsftpd服务器

    安装: [root@server ~]# yum install -y vsftpd [root@server ~]# rpm -ql vsftpd /etc/logrotate.d/vsftpd / ...

  10. BZOJ_5338_ [TJOI2018]xor_可持久化trie

    BZOJ_5338_ [TJOI2018]xor_可持久化trie Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 ...