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

CrossDolphin發表於2016-07-07



連結:戳這裡


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)-1
using 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;
}
/*
5
1 1 1 1 1
1 1 1 1 1
*/


為什麼可以這樣,因為倍增越往後max肯定越大,同理min肯定越小,所以可以二分快速找

相關文章