Codeforces Round #361 (Div. 2) D RMQ+二分

来源:互联网 发布:淘宝买人心果树 编辑:程序博客网 时间:2024/06/05 07:06



链接:戳这里


D. Friends and Subsequences
time limit per test2 seconds
memory limit per test512 megabytes
inputstandard input
outputstandard output
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.

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 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个数ai和bi

在区间[l,r]中存在max(al~ar)==min(bl~br) 问这样的区间有多少个


思路:

题目很经典,我们先用RMQ处理出区间[l,r]的最值,方便log去访问

为什么可以这样,因为倍增越往后max肯定越大,同理min肯定越小,所以可以二分快速找

那么我们固定区间[l,r]上的l,再去找符合要求的r

很容易发现满足这个条件的r肯定也是一段距离

那么什么时候是满足要求呢?

当枚举的区间为[i,r1] (i是定死的)内正好max(ai~ar1)==min(bi~br1) 表示这一段是满足的 ->ans+1

那么接下来从[r1~n]区间里还能不能延长r1使得也满足情况

那么只需要找出一个r2使得这个区间的max(a)正好大于min(b),这样作为分界点去统计答案


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<string>#include<vector>#include <ctime>#include<queue>#include<set>#include<map>#include<stack>#include<iomanip>#include<cmath>#define mst(ss,b) memset((ss),(b),sizeof(ss))#define maxn 0x3f3f3f3f#define MAX 1000100///#pragma comment(linker, "/STACK:102400000,102400000")typedef long long ll;typedef unsigned long long ull;#define INF (1ll<<60)-1using namespace std;int n;int a[200100],b[200100];int rmq1[200100][20],rmq2[200100][20];int query1(int l,int r){    int m=log(r-l+1)/log(2);    return max(rmq1[l][m],rmq1[r-(1<<m)+1][m]);}int query2(int l,int r){    int m=log(r-l+1)/log(2);    return min(rmq2[l][m],rmq2[r-(1<<m)+1][m]);}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]);    a[++n]=2e9;b[n]=-2e9;    for(int i=1;i<=n;i++) rmq1[i][0]=a[i];    for(int i=1;i<=n;i++) rmq2[i][0]=b[i];    int m=log(n)/log(2);    for(int i=1;i<=m;i++){        for(int j=n;j>=1;j--){            rmq1[j][i]=rmq1[j][i-1];            if(j+(1<<(i-1))<=n)                rmq1[j][i]=max(rmq1[j][i],rmq1[j+(1<<(i-1))][i-1]);        }    }    for(int i=1;i<=m;i++){        for(int j=n;j>=1;j--){            rmq2[j][i]=rmq2[j][i-1];            if(j+(1<<(i-1))<=n)                rmq2[j][i]=min(rmq2[j][i],rmq2[j+(1<<(i-1))][i-1]);        }    }    ll ans=0;    for(int i=1;i<=n;i++){        if(a[i]>b[i]) continue;        int l=i,r=n,mid,L=-1;        while(l<r){            mid=(l+r)/2;            if(query1(i,mid)>=query2(i,mid)){                L=mid;                r=mid;            } else l=mid+1;        }        if(L==-1) continue;        l=i;r=n;        int R=i;        while(l<r){            mid=(l+r)/2;            if(query1(i,mid)>query2(i,mid)){                R=mid;                r=mid;            } else l=mid+1;        }        if(query1(i,l)>query2(i,l)) R=l;        ans+=R-L;    }    printf("%I64d\n",ans);    return 0;}/*51 1 1 1 11 1 1 1 1*/


为什么可以这样,因为倍增越往后max肯定越大,同理min肯定越小,所以可以二分快速找
0 0