【BZOJ4149】[AMPPZ2014]Global Warming

Description

给定一个序列a[1],a[2],...,a[n]。请从中选出一段连续子序列,使得该区间最小值唯一、最大值也唯一。
输出选出的子序列的长度的最大值以及取到最大值时左端点的最小值。

Input

第一行包含一个正整数n(1<=n<=500000),表示序列长度。
第二行包含n个正整数,依次表示a[1],a[2],...,a[n](-10^9<=a[i]<=10^9)。

Output

包含一行两个整数l,k,其中l表示选出的子序列的长度的最大值,k表示取到最大值时左端点的最小值。

Sample Input

10
8 3 2 5 2 3 4 6 3 6

Sample Output

6 4

HINT

选出的子序列为5,2,3,4,6,3,只有唯一的最小值2和唯一的最大值6。

题解:首先我们用单调栈枚举每个数作为最大值的影响区间,然后枚举这个最大值。此时最小值怎么取呢?由于我们已经确定了最大值以及最大值的影响区间,那么最小值一定是取这个区间中的最小值,因为其他数的影响区间一定不会比最小值的影响区间大。区间最小值可以用RMQ处理。但是区间中可能有多个最小值,而影响区间包含当前最大值的只有一个,所以我们用vector维护每个数的所有出现位置,然后二分找到当前位置的前驱即后继,合法的最小值要么是前驱要么是后继。然后求一下最大值和最小值影响区间的交集即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=500010;
int n,m,top,ans,pos;
int v[maxn],mn[20][maxn],Log[maxn],lm[maxn],rm[maxn],ln[maxn],rn[maxn],st[maxn];
vector<int> p[maxn];
struct number
{
int val,org;
}num[maxn];
bool cmp(const number &a,const number &b)
{
return a.val<b.val;
}
inline int getmn(int a,int b)
{
int k=Log[b-a+1];
return min(mn[k][a],mn[k][b-(1<<k)+1]);
}
inline void updata(int a,int b)
{
if(a>ans||(a==ans&&b<pos)) ans=a,pos=b;
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
int main()
{
n=rd();
int i,j,a,b;
for(i=1;i<=n;i++) num[i].val=rd(),num[i].org=i;
sort(num+1,num+n+1,cmp);
for(i=1;i<=n;i++)
{
if(i==1||num[i].val>num[i-1].val) m++;
v[num[i].org]=m;
}
for(i=2;i<=n;i++) Log[i]=Log[i>>1]+1;
for(i=1;i<=n;i++) p[v[i]].push_back(i),mn[0][i]=v[i];
for(j=1;(1<<j)<=n;j++) for(i=1;i+(1<<j)-1<=n;i++) mn[j][i]=min(mn[j-1][i],mn[j-1][i+(1<<(j-1))]);
for(st[top=0]=0,i=1;i<=n;i++)
{
while(top&&v[st[top]]<v[i]) top--;
lm[i]=st[top]+1,st[++top]=i;
}
for(st[top=0]=0,i=1;i<=n;i++)
{
while(top&&v[st[top]]>v[i]) top--;
ln[i]=st[top]+1,st[++top]=i;
}
for(st[top=0]=n+1,i=n;i>=1;i--)
{
while(top&&v[st[top]]<v[i]) top--;
rm[i]=st[top]-1,st[++top]=i;
}
for(st[top=0]=n+1,i=n;i>=1;i--)
{
while(top&&v[st[top]]>v[i]) top--;
rn[i]=st[top]-1,st[++top]=i;
}
for(i=1;i<=n;i++)
{
j=getmn(lm[i],rm[i]);
b=lower_bound(p[j].begin(),p[j].end(),i)-p[j].begin(),a=b-1;
if(a>=0&&rn[p[j][a]]>=i) updata(min(rm[i],rn[p[j][a]])-max(lm[i],ln[p[j][a]])+1,max(lm[i],ln[p[j][a]]));
if(b<(int)p[j].size()&&ln[p[j][b]]<=i) updata(min(rm[i],rn[p[j][b]])-max(lm[i],ln[p[j][b]])+1,max(lm[i],ln[p[j][b]]));
}
printf("%d %d\n",ans,pos);
return 0;
}

【BZOJ4149】[AMPPZ2014]Global Warming 单调栈+RMQ+二分的更多相关文章

  1. bzoj4149: [AMPPZ2014]Global Warming

    头都烂了怎么头疼啊 考虑先做出对于一个位置以它作为唯一最小值的最远区间,这个可以单调栈上二分搞出来 那么对于一个位置这个区间而言,一定是选择这个区间的最大数是作为最终的唯一最大数最优的 为什么呢?我们 ...

  2. BZOJ1767/Gym207383I CEOI2009 Harbingers 斜率优化、可持久化单调栈、二分

    传送门--BZOJCH 传送门--VJ 注:本题在BZOJ上是权限题,在Gym里面也不能直接看,所以只能在VJ上交了-- 不难考虑到这是一个\(dp\). 设\(dep_x\)表示\(x\)在树上的带 ...

  3. Bad Hair Day [POJ3250] [单调栈 或 二分+RMQ]

    题意Farmer John的奶牛在风中凌乱了它们的发型……每只奶牛都有一个身高hi(1 ≤ hi ≤ 1,000,000,000),现在在这里有一排全部面向右方的奶牛,一共有N只(1 ≤ N ≤ 80 ...

  4. BZOJ.4540.[HNOI2016]序列(莫队/前缀和/线段树 单调栈 RMQ)

    BZOJ 洛谷 ST表的一二维顺序一定要改过来. 改了就rank1了哈哈哈哈.自带小常数没办法. \(Description\) 给定长为\(n\)的序列\(A_i\).\(q\)次询问,每次给定\( ...

  5. HUID 5558 Alice's Classified Message 后缀数组+单调栈+二分

    http://acm.hdu.edu.cn/showproblem.php?pid=5558 对于每个后缀suffix(i),想要在前面i - 1个suffix中找到一个pos,使得LCP最大.这样做 ...

  6. UVALive 6531 Go up the ultras 单调栈+RMQ

    题目链接:点击打开链接 题意: 给定n座山 以下n个数字表示n座山的高度 若这座山u合法,则要满足: 1.若u的左边存在比u高的山,设v是u左边距离u近期的且严格比u高的山,在[v,u]之间至少有一座 ...

  7. The Preliminary Contest for ICPC Asia Xuzhou 2019 E XKC's basketball team [单调栈上二分]

    也许更好的阅读体验 \(\mathcal{Description}\) 给n个数,与一个数m,求\(a_i\)右边最后一个至少比\(a_i\)大\(m\)的数与这个数之间有多少个数 \(2\leq n ...

  8. 【HNOI2016】序列 莫队+单调栈+RMQ

    Description 给定长度为n的序列:a1,a2,…,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,ar-1,ar.若1≤l≤s≤t≤r≤n,则称a ...

  9. 51nod 1962区间计数(单调栈加二分)

    题目要求是求出两个序列中处于相同位置区间并且最大值相同的区间个数,我们最直观的感受就是求出每个区间的最大值,这个可以O(N)的求,利用单调栈求出每个数作为最大值能够覆盖的区间. 然后我们可以在进行单调 ...

随机推荐

  1. MySQL 源代码scr.rpm安装的一点注意事项

    rpm安装包通常为二进制包(Binary)以及源代码包(Source)两种形式. 在使用源代码方式安装MySQL的时候,官方站点上下载的源代码包通常为scr.rpm格式,而不是直接的tar包.对此,须 ...

  2. UI领域中常常听见的''modal''到底是什么?

    模态窗口其实就是个弹窗.... 问题总结 用户需要采取操作或取消覆盖,直到他可以继续与原始页面进行交互, 这是最原始的modal定义, 本质上是页面在时间维度上的中断系统: 来自wiki百科: Mod ...

  3. 关于Javascript判断变量是否为空

    如何判断Javascript对象是否存在 原文网址:http://www.ruanyifeng.com/blog/2011/05/how_to_judge_the_existence_of_a_glo ...

  4. 谷哥的小弟学后台(04)——MySQL(4)

    探索Android软键盘的疑难杂症 深入探讨Android异步精髓Handler 具体解释Android主流框架不可或缺的基石 站在源代码的肩膀上全解Scroller工作机制 Android多分辨率适 ...

  5. par函数的adj 参数- 控制文字的对齐方式

    adj 用来控制文字的对齐方式,取值范围为0到1,控制图片中x轴和y轴标签,标题,以及通过text 添加的文字的对齐方式 0表示左对齐,代码示例: par(adj = 0)plot(1:5, 1:5, ...

  6. dwr框架使用总结——简单示例

    1.新建web项目,项目名为dwr 2.导入以下jar包: dwr.jar.classes12.jar.commons-logging-1.0.4.jar和commons-logging.jar 3. ...

  7. easyUI实现(alert)提示框自动关闭的实例代码

    function alert_autoClose(title,msg,icon){  var interval;  var time=1000;  var x=2;  //设置时间2s $.messa ...

  8. 怎样用Javascript定义一个类

    其实Javascript中没有类这个定义,但是有类这个概念.很多人都写过这样的代码,对,没错,就是如下代码,清晰的不能再清晰了,就是一个关键字 function,然后定义一个方法名,方法名后紧跟一对括 ...

  9. CS文件类头注释

    1.修改unity生成CS文件的模板(模板位置:Unity\Editor\Data\Resources\ScriptTemplates 文件名:81-C# Script-NewBehaviourScr ...

  10. js判断用户关闭页面或浏览器

    <html><head><meta http-equiv="Content-Type" content="text/html; charse ...