codeforces Round #361 D. Friends and Subsequences (ST表,二分)

D. Friends and Subsequences


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 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?

Input

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.

Output

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

Examples
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
Note

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 answer3 to any query pair, but !Mike will always answer 1.


           题意:查找两数组有区间最大与最小值相同的区间的个数。

          思路:其中一个序列是区间求最大,最大值递非递减的。另一个求最小值则相反,是非递增的。所以两者必然有一个相同的值 的区间。因此可以枚举起点,二分最大与最小相同的对应区间右断点的左界与右界,(右界 - 左界 +1 ) 就是以枚举的当前点为左端点,区间最大值与最小值相同的区间个数。在查找区间最大与最小时需要用st表来查找,一开始用线段树第七组数据就超时了。

         ST表其实也就是倍增思想。

详细见代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn =3* 1e5+100;
typedef long long LL;
int A[maxn][20];
int B[maxn][20];
int len[maxn];
int n;
void init()
{
	len[1]=0;
	for(int i=2;i<maxn;i++)
	{
		len[i]=len[i-1];
		if((1<<(len[i]+1)) == i) len[i]++;
	}
}
void work(int &n)
{
	int i,j;
	for(i=n;i>=1;i--)
	{
		for(j=1;(i+(1<<j)-1) <=n;j++)
		{
			A[i][j]=max(A[i][j-1],A[i+(1<<(j-1))][j-1]);
			B[i][j]=min(B[i][j-1],B[i+(1<<(j-1))][j-1]);
		}
	}
}
inline int query1(int &l,int &r)
{
	return max(A[l][len[r-l+1]],A[r-(1<<len[r-l+1])+1][len[r-l+1]]);
}
inline int query2(int &l,int &r)
{
	return min(B[l][len[r-l+1]],B[r-(1<<len[r-l+1])+1][len[r-l+1]]);
}
int main()
{
	init();
	int n;
	int i,j;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
		scanf("%d",&A[i][0]);
	for(i=1;i<=n;i++)
		scanf("%d",&B[i][0]);
	work(n);
	LL ans=0;
	for(i=1;i<=n;i++)
	{
		int lo=i-1;
		int ub=n+1;
		int mid;
		while(ub-lo>1)
		{
			mid=(lo+ub)>>1;
			if(query1(i,mid)-query2(i,mid)<0)
				lo=mid;
			else ub=mid;
		}
		if(ub>n) continue;
		int a=ub;
		lo=i-1;ub=n+1;
		while(ub-lo>1)
		{
			mid=(lo+ub)>>1;
			if(query1(i,mid)-query2(i,mid)>0)
				ub=mid;
			else lo=mid;
		}
	
		//cout<<lo<<" "<<a<<endl;		
		lo=min(lo,n);
		if(lo>=a)
		ans=ans+lo-a+1;
	}
	
	cout<<ans<<endl;
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值