codeforces 689D Friends and Subsequences st表+二分

题目:

D. Friends and Subsequences
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard 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 (1 ≤ n ≤ 200 000)的数组a,b,求有多少个区间[l,r]满足

max(al,al+1,...ar) = min( bl,bl+1,...br )。


分析:
涉及到区间最值问题,且两数组都是静态的 优先考虑st表

问总共有多少个区间,可以从左到右另每一个下标i为左端点,找出以该下标为左端点的所有满足要求的区间

要找所有区间,由于左端点已经确定,只需要二分找到满足要求的右端点的最左下标r1和最右下标r2,则总区间数+=(r2-r1+1)


代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=201000;

int n, a[maxn], b[maxn];
int d_min[maxn][20];//第二维开到17还是小... 
int d_max[maxn][20];

void RMQ_init() {
    for(int i=0; i<n; i++) d_max[i][0] = a[i], d_min[i][0] = b[i];
    for(int j=1; (1<<j)<=n; j++)
        for(int i=0; i+(1<<j)-1<n; i++) {
            d_min[i][j] = min(d_min[i][j-1], d_min[i+(1<<(j-1))][j-1]);
            d_max[i][j] = max(d_max[i][j-1], d_max[i+(1<<(j-1))][j-1]);
        }
}

int RMQ_min(int L, int R) {
    int k = 0;
    while((1<<(k+1)) <= R-L+1) k++;
    return min(d_min[L][k], d_min[R-(1<<k)+1][k]);
}

int RMQ_max(int L, int R) {
    int k = 0;
    while((1<<(k+1)) <= R-L+1) k++;
    return max(d_max[L][k], d_max[R-(1<<k)+1][k]);
}

int main(){//311 ms	35100 KB
    while(scanf("%d",&n) == 1){
        for(int i=0; i<n; i++) scanf("%d",&a[i]);
        for(int i=0; i<n; i++) scanf("%d",&b[i]);
        RMQ_init();
        LL ans = 0;
        for(int i=0; i<n; i++) {//枚举每一个左端点 
            if(a[i] > b[i]) continue;
            int first_r=-1, last_r=-1;
            int l=i,r=n-1,mid;
	//用两次二分操作分别求出第一次和最后一次满足min==max的右端点,作差累加即可
            while(l <= r) {
                mid = (l+r) / 2;
                if(RMQ_max(i,mid) == RMQ_min(i,mid)) first_r = mid;
                if(RMQ_max(i,mid) >= RMQ_min(i,mid)) r = mid-1;
                else l = mid+1;
            }
            if(first_r == -1) continue;

            l=i; r=n-1;
            while(l <= r) {
                mid = (l+r) / 2;
                if(RMQ_max(i,mid) > RMQ_min(i,mid)) r = mid-1;
                else l = mid+1, last_r = mid;
            }
            ans += last_r - first_r + 1;
        }
        printf("%I64d\n", ans);
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值