2020五校联盟H-虚假的防AK

原题是CFdiv1的一道B题,虚假2000分,其实只是个单调栈板子。

题意:先求在一个任意连续区间里的最大值和次大值,求二者异或值。然后最终输出所有异或值的最大值。

思路:在任意区间里找到第一个比该位置数大的数,便是一个区间的最大值和次大值了,然后正序逆序各跑一遍,不然会有疏漏,最终单调栈维护O(n)解决问题即可。

AC代码

#include
#include
#include
using namespace std;
const int N = 1e5+4;
#define ll long long
ll l[N],r[N],a[N];
int main()
{
		ll n;
		cin>>n;
		for(ll i=1;i<=n;i++){
			scanf("%d",&a[i]);
		}
		stack <ll> s;
		for(ll i=1;i<=n;i++)
		{
			while(s.size()&&a[s.top()]<=a[i]) s.pop();
			if(s.size()==0) l[i]=i;
			else l[i]=s.top();
			s.push(i);
		}
		while(!s.empty()) s.pop();
		for(ll i=n;i>=1;i--)
		{
			while(s.size()&&a[s.top()]<=a[i]) s.pop();
			if(s.size()==0) r[i]=i;
			else r[i]=s.top();
			s.push(i);
		}
		long long ans=-1;
		for(ll i=1;i<=n;i++)
		{
			ans=max(ans,max(a[l[i]]^a[i],a[i]^a[r[i]]));
		}
		printf("%lld\n",ans);
}

你可能感兴趣的:(单调栈)