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 and b 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 exactly n(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 numbers a1, a2, ..., an ( - 109 ≤ ai ≤ 109) — the sequence a.
The third line contains n integer numbers b1, 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 since max{2} = min{2}.
2.l = 4,r = 5 since max{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.
思路:固定左端点i,显然两个数列右方的max和min分别递增和递减,那么二分出max和min相等处的左右边界即可。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e5+3;
int n, a[maxn], b[maxn];
int mi[21][maxn], mx[21][maxn], tlog[maxn], p[21];
void init()
{
p[0] = 1;tlog[0] = -1;
for(int i=1; i<21; ++i) p[i] = p[i-1]*2;
for(int i=1; i<=n; ++i) tlog[i] = (i&(i-1))?tlog[i-1]:(tlog[i-1]+1);
for(int i=1; i<=n; ++i) mi[0][i] = b[i], mx[0][i] = a[i];
for(int i=1; p[i]<=n; ++i)
for(int j=1; j+p[i]-1<=n; ++j)
{
mi[i][j] = min(mi[i-1][j], mi[i-1][j+p[i-1]]);
mx[i][j] = max(mx[i-1][j], mx[i-1][j+p[i-1]]);
}
}
int get_mx(int l, int r)
{
int k = tlog[r-l+1];
return max(mx[k][l], mx[k][r-p[k]+1]);
}
int get_mi(int l, int r)
{
int k = tlog[r-l+1];
return min(mi[k][l], mi[k][r-p[k]+1]);
}
int lower(int s)
{
int l=s, r=n;
while(l<=r)
{
int mid = l+r>>1;
if(get_mx(s, mid)<get_mi(s, mid)) l = mid+1;
else r= mid-1;
}
return r;
}
int upper(int s)
{
int l=s, r=n;
while(l<=r)
{
int mid = l+r>>1;
if(get_mx(s, mid)<=get_mi(s, mid)) l = mid+1;
else r = mid-1;
}
return r;
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
for(int i=1; i<=n; ++i) scanf("%d",&b[i]);
init();
LL ans = 0;
for(int i=1; i<=n; ++i)
ans += upper(i)-lower(i);
printf("%I64d\n",ans);
return 0;
}