求助 WA on #23
查看原帖
求助 WA on #23
353688
王熙文楼主2021/12/27 22:35

rt,思路是用 st 表,枚举左端点然后二分重合的部分,第一次二分第一次重合,第二次二分最后一次,相减即结果。

#include<bits/stdc++.h>
using namespace std;

int a[200010],b[200010];

int lg2[200010];

int st1[20][200010],st2[20][200010];

int query(int which,int l,int r)
{
	int len=lg2[r-l+1];
	if(which==1) return max(st1[len][l],st1[len][r-(1<<len)+1]);
	else return min(st2[len][l],st2[len][r-(1<<len)+1]);
}

int main()
{
	int n;
	long long ans=0;
	scanf("%d",&n);
	for(int i=1; i<=n; ++i)
	{
		scanf("%d",&a[i]);
		st1[0][i]=a[i];
	}
	for(int i=1; i<=n; ++i)
	{
		scanf("%d",&b[i]);
		st2[0][i]=b[i];
	}
	for(int i=2; i<=n; ++i) lg2[i]=lg2[i>>1]+1;
	for(int i=1; i<=18; ++i)
	{
		for(int j=1; j+(1<<i)-1<=n; ++j)
		{
			st1[i][j]=max(st1[i-1][j],st1[i-1][j+(1<<i-1)]);
			st2[i][j]=min(st2[i-1][j],st2[i-1][j+(1<<i-1)]);
		}
	}
	for(int i=1; i<=n; ++i)
	{
		int l=i,r=n,ans1=114514,ans2=-114514,mid;
		while(l<=r)
		{
			mid=(l+r)>>1;
			if(query(1,i,mid)>=query(2,i,mid))
			{
				r=mid-1;
				ans1=mid;
			}
			else l=mid+1;
		}
		l=i,r=n;
		while(l<=r)
		{
			mid=(l+r)>>1;
			if(query(1,i,mid)<=query(2,i,mid))
			{
				l=mid+1;
				ans2=mid;
			}
			else r=mid-1;
		}
		ans+=max(ans2-ans1+1,0);
	}
	printf("%lld",ans);
	return 0;
}

本地对拍拍不出来 /kel

2021/12/27 22:35
加载中...