1. 程式人生 > >【BZOJ4149】[AMPPZ2014]Global Warming 單調棧+RMQ+二分

【BZOJ4149】[AMPPZ2014]Global Warming 單調棧+RMQ+二分

以及 其他 getchar light tor span upd 維護 log

【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+二分