题目链接 看过来
题意
给定两个长度为
n
n
的数列,问有多少个区间
[L,R](0≤L≤R<n)
[
L
,
R
]
(
0
≤
L
≤
R
<
n
)
满足
max(al,al+1,...,ar)=min(bl,bl+1,...,br)
m
a
x
(
a
l
,
a
l
+
1
,
.
.
.
,
a
r
)
=
m
i
n
(
b
l
,
b
l
+
1
,
.
.
.
,
b
r
)
。
题解
考虑固定起点,则 max m a x 数组是非递减的, min m i n 数组是非递增的,那么我们可以用 RMQ R M Q 预处理区间的最大值和最小值,然后用二分查找(手写 lowerbound和upperbound)找到满足max=min的区间右端点的所有可能值 l o w e r b o u n d 和 u p p e r b o u n d ) 找 到 满 足 m a x = m i n 的 区 间 右 端 点 的 所 有 可 能 值
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
int a[maxn],b[maxn],n;
int d1[maxn][21],d2[maxn][21];
void rmq_init()
{
for(int i=0;i<n;++i){
d1[i][0]=a[i];
d2[i][0]=b[i];
}
for(int j=1;(1<<j)<=n;++j)
for(int i=0;i+(1<<j)-1<n;++i){
d1[i][j]=max(d1[i][j-1],d1[i+(1<<(j-1))][j-1]);
d2[i][j]=min(d2[i][j-1],d2[i+(1<<(j-1))][j-1]);
}
}
int rmq1(int l,int r)
{
int k=0;
while((1<<(k+1))<=r-l+1) ++k;
return max(d1[l][k],d1[r-(1<<k)+1][k]);
}
int rmq2(int l,int r)
{
int k=0;
while((1<<(k+1))<=r-l+1) ++k;
return min(d2[l][k],d2[r-(1<<k)+1][k]);
}
ll solve(){
ll ans=0;
for(int i=0;i<n;++i){
int l=i,r=n,mid1,mid2;
while(l<r){
mid1=(r+l)/2;
if(rmq1(i,mid1)>=rmq2(i,mid1)) r=mid1;
else l=mid1+1;
}
mid1=l;
l=i; r=n;
while(l<r){
mid2=(r+l)/2;
if(rmq1(i,mid2)<=rmq2(i,mid2)) l=mid2+1;
else r=mid2;
}
mid2=l;
ans+=(ll)( (ll)mid2 - (ll)mid1);
}
return ans;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;++i) scanf("%d",a+i);
for(int i=0;i<n;++i) scanf("%d",b+i);
rmq_init();
printf("%I64d\n",solve() );
return 0;
}