奶牛排序——RMQ
【问题描述】
奶牛在熊大妈的带领下排成了一条直队。
显然,不同的奶牛身高不一定相同……
现在,奶牛们想知道,如果找出一些连续的奶牛,要求最左边的奶牛 A 是最矮的,最右
边的 B 是最高的,且 B 高于 A 奶牛,且中间如果存在奶牛,则身高不能和 A、B 奶牛相同,
问这样的一些奶牛最多会有多少头。
从左到右给出奶牛的身高,请告诉它们符合条件的最多的奶牛数(答案可能是零、二,
但不会是一)。
【输入格式】
第一行一个数 N(2<=N<=100000),表示奶牛的头数。
接下来 N 个数,每行一个数,从上到下表示从左到右奶牛的身高(1<=身高
<=maxlongint)。
【输出格式】
一行,表示最多奶牛数。
【输入样例】Tahort.in
5
1
2
3
4
1
【输出样例】Tahort.out
4
【 样例解析 】
取第 1 头到第 4 头奶牛,满足条件且为最多。
这道题的思路如下:我们可以首先找到整个区间内最高的牛所在的位置和最矮的牛所在的位置。这样的话,答案区间就不可能越过这两头牛了,之后将区间分开递归求解即可。如果高的牛(maxn)在矮的牛(minn)前面,那么递归搜索
(l,maxn),(maxn+1,minn-1),(minn,r) ,如果矮的牛在高的牛前面,那么我们直接用maxn-minn+1更新答案,之后递归搜索(l,minn-1),(maxn+1,r)即可。
这样的话问题就转化成了如何快速求任意一段区间内的最大最小值的位置。这是一个典型的RMQ问题,我们选择使用st表解决。既然只求最大最小值的位置,那么我们就可以不使用st表存值,这样不仅好写而且时间还短。具体的做法就是我们自定义函数来比较编号,每次比较大小结束之后记录当前区间内最大(小)值的位置即可。这样每次递归访问的时候,我们甚至可以做到O(1)。
这道题有很多地方还是非常坑的,比如说你写一个十分正确的RMQ在Lemon或者本机上运行都会导致RE,据说可能是因为递归层数过多而爆栈,这个自己本人调试也调不出来,你只会看到程序在输入所有数据之后报错。可以使用vijos代测,但是我的程序前几次提交全部TLE,结果最后采用了一个优化,就是如果递归的区间长度小于当前的答案就直接返回无需搜索。但还是不行……最后发现是因为开了全局变量的缘故,开成局部变量就过了……蒟蒻至今搞不明白是为什么。
最后上一下代码吧。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
using namespace std;
const int N = ,M = ;
typedef long long ll;
int n,h[N],max1[N][M],min1[N][M],ans1;
int read()
{
int ans = ;
char ch,last = ' ';
ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-') ch = last;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
ans *= ;
ans += ch - '';
ch = getchar();
}
if(last == '-') ans = -ans;
return ans;
}
int fmax(int c,int d)//自定义比较编号的函数
{
if(h[c] > h[d] || (h[c] == h[d] && c < d)) return c;
else return d;
}
int fmin(int c,int d)
{
if(h[c] < h[d] || (h[c] == h[d] && c > d)) return c;
else return d;
}
void ask(int l,int r)
{
if(l >= r || ans1 >= r-l+) return;//这个优化可以省很多时间
int k = log2(r-l+);//注意这里开cstdlib
int g = << k;
int maxn = fmax(max1[l][k],max1[r-g+][k]);
int minn = fmin(min1[l][k],min1[r-g+][k]);//就是这两行坑了无数次!!!
if(maxn == minn) return;
if(maxn > minn)
{
ans1 = max(ans1,maxn-minn+);//更新并递归
ask(l,minn-);
ask(maxn+,r);
return;
}
else
{
ask(l,maxn);
ask(maxn+,minn-);
ask(minn,r);
return;
}
}
int main()
{
n = read();
rep(i,,n)
{
h[i] = read();
max1[i][] = i;
min1[i][] = i;
}
int q = log2(n);
rep(j,,q)
{
for(int i = ;i+(<<j)-<=n;i++)
{
max1[i][j] = fmax(max1[i][j-],max1[i+(<<(j-))][j-]);
min1[i][j] = fmin(min1[i][j-],min1[i+(<<(j-))][j-]);
}//st表求最大最小值
}
ask(,n);
printf("%d\n",ans1);
return ;
}
奶牛排序——RMQ的更多相关文章
- 牛客假日团队赛2 H.奶牛排序
链接: https://ac.nowcoder.com/acm/contest/924/H 题意: 农夫JOHN准备把他的 N(1 <= N <= 10,000)头牛排队以便于行动.因为脾 ...
- BZOJ2815:[ZJOI2012]灾难(拓扑排序,LCA)
Description 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过 ...
- POJ -3190 Stall Reservations (贪心+优先队列)
http://poj.org/problem?id=3190 有n头挑剔的奶牛,只会在一个精确时间挤奶,而一头奶牛需要占用一个畜栏,并且不会和其他奶牛分享,每头奶牛都会有一个开始时间和结束时间,问至少 ...
- USACO 2001 OPEN
第1题 绿组. 奶牛接力赛[relay] 题目描述 农夫约翰已经为一次赛跑选出了K(2≤K≤40)头牛组成了一支接力队.赛跑在农夫约翰所拥有的农场上进行,农场的编号为1到Ⅳf4≤Ⅳ< 800), ...
- POJ2376 Cleaning Shifts
题意 POJ2376 Cleaning Shifts 0x50「动态规划」例题 http://bailian.openjudge.cn/practice/2376 总时间限制: 1000ms 内存限制 ...
- POJ 2010 Moo University - Financial Aid (优先队列)
题意:从C头奶牛中招收N(奇数)头.它们分别得分score_i,需要资助学费aid_i.希望新生所需资助不超过F,同时得分中位数最高.求此中位数. 思路: 先将奶牛排序,考虑每个奶牛作为中位数时,比它 ...
- 【贪心】洛谷P1607 [USACO09FEB]庙会班车Fair Shuttle 题解
不是很容易写出正解的贪心问题. 题目描述 Although Farmer John has no problems walking around the fair to collect pri ...
- poj3171 Cleaning Shifts
传送门 题目大意 有一个大区间和n个小区间,每个小区间都有一个代价,求最少付出多少代价可以使得小区间完全覆盖大区间. 分析为了方便起见我们先将s变为2,其它的位置都对应更改以便后期处理.我们考虑以t1 ...
- 【POJ - 2376】Cleaning Shifts(贪心)
Cleaning Shifts Descriptions: 原文是English,我这就直接上Chinese了,想看原文的点一下链接哦 大表哥分配 N (1 <= N <= 25,000) ...
随机推荐
- CDOJ_844 程序设计竞赛
原题地址:http://acm.uestc.edu.cn/#/problem/show/844 "你动规无力,图论不稳,数据结构松散,贪心迟钝,没一样像样的,就你还想和我同台竞技,做你的美梦 ...
- JavaScript 函数作用域的“提升”现象
在JavaScript当中,定义变量通过var操作符+变量名.但是不加 var 操作符,直接赋值也是可以的.例如 : message = "hello JavaScript ! " ...
- sshd登录攻击
先说简单的防范措施: 1.密码足够复杂 密码的长度大于8位.有数字.大小写字母.特殊字符组合. 2.nmap 扫描 为了避免被扫描到, #看到端口是81 ssh root@192.168.1.63 玩 ...
- 转: CentOS 6 使用 yum 安装MongoDB及服务器端配置
转: http://www.cnblogs.com/shanyou/archive/2012/07/14/2591838.html CentOS 6 使用 yum 安装MongoDB及服务器端配置 ...
- C/C++知识要点2——STL中Vector、Map、Set容器的实现原理
1.Vector是顺序容器.是一个动态数组.支持随机存取.插入.删除.查找等操作,在内存中是一块连续的空间.在原有空间不够情况下自己主动分配空间.添加为原来的两倍.vector随机存取效率高,可是在v ...
- palindrome-partitioning I&II——回文切割、深度遍历
I: Given a string s, partition s such that every substring of the partition is a palindrome. Return ...
- libxml/HTMLparser.h file not found
在导入asihttprequest包时出问题导入了libxml2.dylib.可是却提示libxml/HTMLparser.h file not found. 这是由于你的开发环境默认的路径无法找到这 ...
- C#不用union,而是有更好的方式实现 .net自定义错误页面实现 .net自定义错误页面实现升级篇 .net捕捉全局未处理异常的3种方式 一款很不错的FLASH时种插件 关于c#中委托使用小结 WEB网站常见受攻击方式及解决办法 判断URL是否存在 提升高并发量服务器性能解决思路
C#不用union,而是有更好的方式实现 用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便.那C# ...
- BAT&注册表重定向劫持
RunJS 常用引导,有时启动某个应用需要环境变量可以这样启动应用,会对启动的进程生效,即被继承 set PATH=D:\Developer\sdk\platform-tools;%PATH% D: ...
- Hibernate commit() 和flush() 的区别
<<精通Hibernate java对象持久化技术详解>> ,flush()方法进行清理缓存的操作,执行一系列的SQL语句,但不会提交事务;commit()方法会先调用flus ...