您的位置:首页 > 产品设计 > UI/UE

codeforces 361 D - Friends and Subsequences

2016-07-13 10:56 344 查看
原题:

Description

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?

Input

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.

Output

Print the only integer number — the number of occasions the robot will count, thus for how many pairs

is satisfied.

Sample Input

Input
6
1 2 3 2 1 4
6 7 1 2 3 2


Output
2


Input
3
3 3 3
1 1 1


Output
0


Hint

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.

提示: 暴力比对所有区间时间复杂度是(n^2)无法通过。

观察发现,如果固定区间左边界L,右边界R一次递增,a_max【L,R】是不减的,即有序。 同样b_min【L,R】是不增的,有序。

所以就可以先枚举左端点,再用二分法去寻找右端点的合法(符合题意的)区间,这个区间会是一个连续的范围。

二分的时候注意 RMQ_a(L,mid) = RMQ_b(L,mid) 的时候如何处理决定了最终结果是右端点的左边界还是右边界。

求区间最值是使用了RMQ算法。(一个很精妙的算法,我之前的博客里有写。)

代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>

using namespace std;

#define  MAX(x,y) (((x)>(y)) ? (x) : (y))
#define  MIN(x,y) (((x) < (y)) ? (x) : (y))
#define ABS(x) ((x)>0?(x):-(x))
#define ll long long

const int inf = 0x7fffffff;
const int maxn=2e5+10;

int a[maxn],b[maxn];
int d_a[maxn][23];
int d_b[maxn][23];

void RMQ_init_a(int *A,int n)
{
for(int i=0; i<n; i++)  d_a[i][0]=A[i];
for(int j=1; (1<<j)-1 < n; j++)
for(int i=0; i+(1<<j)-1 < n; i++)
d_a[i][j]=MAX( d_a[i][j-1], d_a[i + (1<<(j-1))][j-1] );
}

int RMQ_a(int L, int R)
{
int k=0;
while( 1<<(k+1) <= R-L+1 )  k++;
return MAX( d_a[L][k], d_a[R-(1<<k) + 1][k] );
}

void RMQ_init_b(int *A,int n)
{
for(int i=0; i<n; i++)  d_b[i][0]=A[i];
for(int j=1; (1<<j)-1 < n; j++)
for(int i=0; i+(1<<j)-1 < n; i++)
d_b[i][j]=MIN( d_b[i][j-1], d_b[i + (1<<(j-1))][j-1] );
}

int RMQ_b(int L, int R)
{
int k=0;
while( 1<<(k+1) <= R-L+1 )  k++;
return MIN( d_b[L][k], d_b[R-(1<<k) + 1][k] );
}

int main()
{
int n;
cin>>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_a(a,n);
RMQ_init_b(b,n);
int left, right;
ll ans = 0;
for(int L=0; L<n; L++)
{
int left = inf, right = -inf;
//求左边界
int l = L;
int r = n-1;
while(l <= r)
{
int mid=(l + r)/2;
if(RMQ_a(L,mid) > RMQ_b(L,mid)) //左半部分
r=mid-1;
else if(RMQ_a(L,mid) < RMQ_b(L,mid))                             //右半部分
l=mid+1;
else
{
left = min(left, mid);
r=mid-1;
}
}
//        printf("left = %d\n",left);
//求右边界
l = L;
r = n-1;
while(l <= r)
{
int mid=(l + r)/2;
if(RMQ_a(L,mid) > RMQ_b(L,mid)) //左半部分
{
r=mid-1;
}
else if(RMQ_a(L,mid) < RMQ_b(L,mid))                          //右半部分
l=mid+1;
else
{
right = max(right, mid);
l=mid+1;
}
}
//        printf("right = %d\n",right);
if(left != inf)
ans += right - left + 1;
}
cout<<ans<<endl;

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: