题目
Mike and !Mike are old childhood rivals, they are opposite in everything they do, except programming. Today they have a problem they cannot solve on their own, but together (with you) — who knows?
Every one of them has an integer sequences a andb of length n. Being given a query of the form of pair of integers(l, r), Mike can instantly tell the value of while !Mike can instantly tell the value of.
Now suppose a robot (you!) asks them all possible different queries of pairs of integers(l, r) (1 ≤ l ≤ r ≤ n) (so he will make exactlyn(n + 1) / 2 queries) and counts how many times their answers coincide, thus for how many pairs is satisfied.
How many occasions will the robot count?
The first line contains only integer n (1 ≤ n ≤ 200 000).
The second line contains n integer numbersa1, a2, ..., an ( - 109 ≤ ai ≤ 109) — the sequence a.
The third line contains n integer numbersb1, b2, ..., bn ( - 109 ≤ bi ≤ 109) — the sequence b.
Print the only integer number — the number of occasions the robot will count, thus for how many pairs is satisfied.
6 1 2 3 2 1 4 6 7 1 2 3 2
2
3 3 3 3 1 1 1
0
The occasions in the first sample case are:
1.l = 4,r = 4 sincemax{2} = min{2}.
2.l = 4,r = 5 sincemax{2, 1} = min{2, 3}.
There are no occasions in the second sample case since Mike will answer 3 to any query pair, but !Mike will always answer 1.
题意
解法
代码
#include<cstdio>
#define LL long long
int a[200005],b[200005],maxa[200005][30],minb[200005][30];
int max(int a,int b)
{
return a>b?a:b;
}
int min(int a,int b)
{
return a<b?a:b;
}
void pre(int n)
{
int i,j;
for(i=0;i<n;i++)
{
maxa[i][0]=a[i];
minb[i][0]=b[i];
}
for(j=1;(1<<j)<=n;j++)
for(i=0;i+(1<<j)-1<n;i++)
{
maxa[i][j]=max(maxa[i][j-1],maxa[i+(1<<(j-1))][j-1]);
minb[i][j]=min(minb[i][j-1],minb[i+(1<<(j-1))][j-1]);
}
}
int rmq(int l,int r,int ty)//ty是1表示询问a在[l,r]上的最大值,0则是询问b在[l,r]上的最小值
{
int k=0;
while((1<<(k+1))<=r-l+1) k++;
if(ty)
return max(maxa[l][k],maxa[r-(1<<k)+1][k]);
else
return min(minb[l][k],minb[r-(1<<k)+1][k]);
}
int main()
{
int n,i;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
scanf("%d",&b[i]);
pre(n);
LL ans=0;
for(i=0;i<n;i++)
{
int l=i,r=n-1,mid,flag=0;
//二分左端点
while(l<=r)
{
mid=(l+r)/2;
int ma=rmq(i,mid,1);
int mi=rmq(i,mid,0);
if(ma==mi)
{
flag=1;
}
if(ma>mi)
r=mid-1;
else
l=mid+1;
}
if(flag==0)//如果没有一个区间使最大值等于最小值,二分是无效的
continue;
int ans1=r;
l=i,r=n-1;
//二分右端点
while(l<=r)
{
mid=(l+r)/2;
int ma=rmq(i,mid,1);
int mi=rmq(i,mid,0);
if(ma<mi)
l=mid+1;
else
r=mid-1;
}
int ans2=l;
if(flag)
ans=ans+(LL)(ans1-ans2+1);
}
printf("%I64d\n",ans);
return 0;
}