codeforces 689D (二分 RMQ)

来源:互联网 发布:直播软件收入排行榜 编辑:程序博客网 时间:2024/05/22 02:03

题目链接:点击这里

题意:给出两个数列, 有多少对[l,r]满足max{al,al+1...ar}=min{bl,bl+1...br}

如果固定一个左端点,max数组是递增的,min是递减的, 那么需要寻找一段右端点使得区间的max-min等于0. 这个可以通过枚举下标然后rmq询问最大最小得到。因为rmq预处理之后的询问是O(1)的,所以总复杂度是O(nlgn)。

#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <cmath>#include <map>using namespace std;#define maxn 200005int n;int a[maxn], b[maxn];int dp1[maxn][21], dp2[maxn][21];void rmq_init () {    for (int i = 0; i < n; i++) dp1[i][0] = a[i];    for (int j = 1; (1<<j) <= n; j++) {        for (int i = 0; i+(1<<j)-1 < n; i++) {            dp1[i][j] = max (dp1[i][j-1], dp1[i+(1<<(j-1))][j-1]);        }    }    for (int i = 0; i < n; i++) dp2[i][0] = b[i];    for (int j = 1; (1<<j) <= n; j++) {        for (int i = 0; i+(1<<j)-1 < n; i++) {            dp2[i][j] = min (dp2[i][j-1], dp2[i+(1<<(j-1))][j-1]);        }    }}int rmq_max (int l, int r) {    int k = 0;    while ((1<<(k+1)) <= r-l+1) k++;    return max (dp1[l][k], dp1[r-(1<<k)+1][k]);}int rmq_min (int l, int r) {    int k = 0;    while ((1<<(k+1)) <= r-l+1) k++;    return min (dp2[l][k], dp2[r-(1<<k)+1][k]);}void solve () {    rmq_init ();    long long ans = 0;    for (int i = 0; i < n; i++) {        int l = i, r = n-1;        while (r-l > 1) {            int mid = (l+r)>>1;            if (rmq_min (i, mid)- rmq_max (i, mid) > 0) l = mid;            else r = mid;        }        int L;        if (rmq_min (i, l) - rmq_max (i, l) == 0) L = l;        else if (rmq_min (i, r) - rmq_max (i, r) == 0) L = r;        else continue;        l = i, r = n-1;        while (r-l > 1) {            int mid = (l+r)>>1;            if (rmq_min (i, mid) - rmq_max (i, mid) < 0) r = mid;            else l = mid;        }         int R;        if (rmq_min (i, r) - rmq_max (i, r) == 0) R = r;        else if (rmq_min (i, l) - rmq_max (i, l) == 0) R = l;        else continue;        ans += (R-L+1);    }    cout << ans << endl;}int main () {    cin >> n;    for (int i = 0; i < n; i++) cin >> a[i];    for (int i = 0; i < n; i++) cin >> b[i];    solve ();    return 0;}
0 0