【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. sql 存储过程 in 的两种写法

    最近又忘记存储过程 除了exec 动态写法的另外一种,这里记录一下,方便查找 写法1,动态语句 CREATE PROCEDURE sp_CountShiftWish @strids varchar ( ...

  2. YAML的使用

    YAML 语言教程 编程免不了要写配置文件,怎么写配置也是一门学问.                                      YAML 是专门用来写配置文件的语言,非常简洁和强大,远 ...

  3. PCL,VTK及其依赖库的编译-十分详细

    所有库的编译教程都很详细,全都上传到百度文库. 1.VS2013-Qt5.5.1-动态编译-VTK7.0.0http://wenku.baidu.com/view/749528a433687e21ae ...

  4. C++11 新特性:Lambda 表达式

    参考文章:https://blogs.oracle.com/pcarlini/entry/c_1x_tidbits_lambda_expressions 或许,Lambda 表达式算得上是 C++ 1 ...

  5. php -- 读取文本文件内容

    php读取文件内容的三种方法:    //**************第一种读取方式*****************************  代码如下: header("content- ...

  6. Huffman树

    结点定义: /* * Huffman树结点定义 */ struct Node { ElementType weight; // 结点的权值 struct Node *leftChild; // 结点的 ...

  7. windowmasker 标记基因组中的重复序列和低复杂度序列

    下载地址:ftp://ftp.ncbi.nlm.nih.gov/pub/agarwala/windowmasker/ 在这个目录下 其中windowmasker 为linux 平台的可执行文件 win ...

  8. 基于Nginx反向代理及负载均衡

    基于Nginx反向代理及负载均衡 参考:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass 只要没有被启用,默认就是 ...

  9. android 开发者资源下载地址记录(转+补充)

    https如果无法下载的话将下面的:https://dl-ssl 部分改为 http://dl (1)Android SDK (Android SDK主安装包,包含SDK Manager.AVD Ma ...

  10. 如何创建 SVN 服务器,并搭建自己的 SVN 仓库

    SVN是一个广泛使用的版本控制系统,在日常工作中有广泛的应用空间,比如文档管理,我们就可以搭建一个 SVN 仓库,日常需要归类保存的文档统统上传到仓库中,那如何创建 SVN 服务器, 又如何搭建 SV ...