[悬2关] 90pts 求调 or hack
查看原帖
[悬2关] 90pts 求调 or hack
749325
Sincerin楼主2024/10/8 12:23

ST表和二分,枚举右端点 rr,找最左边的 ll 使得 a[r]a[r] 为区间最大值,然后找 [l,r][l,r] 的第一个后缀最小值出现位置。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector> 
#include<stack> 
#include<map> 
using namespace std;   
#define ri register int
#define rd(n) n=read()
inline int read(void)
{
	register int res=0,f=0;
	register char c=getchar();
	while(c<'0'||c>'9'){f^=(c=='-');c=getchar();}
	while(c>='0'&&c<='9'){res=(res<<3)+(res<<1)+(c^48);c=getchar();}
	return f?-res:res;
}
inline void fprint(int n)
{
	if(n<0){putchar('-');n=-n;}
	if(n>9) fprint(n/10);
	putchar(n%10+'0');
}
inline void print(int n)
{
	fprint(n);
	putchar('\n');
}
const int N=100002;
int n,m,k,x,y,z,ans,res,l,r,a[N];
stack<int>s;
map<int,int>id;
vector<int>pos[N];
int Log[N],ma[N][16],mi[N][16];
void ST(void)
{
	for(ri i=2;i<=n;++i) Log[i]=Log[i>>1]+1;
	for(ri i=1;i<=n;++i) ma[i][0]=mi[i][0]=a[i];
	k=Log[n];
	for(ri i=1;i<=k;++i)
	{
		for(ri j=1;j<=n-(1ll<<i)+1;++j)
		{
			ma[j][i]=max(ma[j][i-1],ma[j+(1ll<<(i-1))][i-1]);
			mi[j][i]=min(mi[j][i-1],mi[j+(1ll<<(i-1))][i-1]);
		}
	}
}
inline int queryma(int l,int r)
{
	k=Log[r-l+1];
	return max(ma[l][k],ma[r-(1ll<<k)+1][k]);
} 
inline int querymi(int l,int r)
{
	k=Log[r-l+1];
	return min(mi[l][k],mi[r-(1ll<<k)+1][k]);
}
signed main(void)
{
	rd(n);
	for(ri i=1;i<=n;++i) rd(a[i]);
	for(ri i=1;i<=n;++i) pos[i].emplace_back(0);
	for(ri i=1;i<=n;++i)
	{
		if(id.find(a[i])==id.end()) id[a[i]]=++m;
		pos[id[a[i]]].emplace_back(i);
	} 
	ST();
	for(ri i=1;i<=n;++i)
	{
		x=id[a[i]];
		y=*--lower_bound(pos[x].begin(),pos[x].end(),i);
		//y is the first pos before i that value[y]=value[i]
		++y;//A<B a[y]==a[i] 
		//cout<<queryma(y,i)<<"\n";
		if(queryma(y,i)>a[i])
		{
			res=y;
			l=y; r=i;
			while(l<=r)
			{
				ri mid=(l+r)>>1;
				if(queryma(mid,i)>a[i]) l=mid+1;
				else
				{
					res=mid;
					r=mid-1;
				}
			}
			y=res;
		}
		//let a[i] become the maximum of range [y,i]
		//cout<<y<<' '<<i<<"\n"; 
		ri ts=querymi(y,i);
		ri tt=id[ts];
		ri ttt=*--lower_bound(pos[tt].begin(),pos[tt].end(),i);
		// ttt is the first pos that a[ttt]==min value of range [y,i]
		//cout<<ttt<<"\n";
		if(ttt>=y) ans=max(ans,i-ttt+1);
	}
	print(ans);
	return 0;
}












2024/10/8 12:23
加载中...