zoukankan      html  css  js  c++  java
  • CF689D Friends and Subsequences 题解 二分答案

    题目链接:https://www.luogu.com.cn/problem/CF689D

    解题思路:因为

    [max_{i=l}^{r} a_i ]

    (r) 单调递增;

    [min_{i=l}^{r} b_i ]

    (r) 单调递减。

    所以我们可以枚举 (l),二分

    [max_{i=l}^{r} a_i = min_{i=l}^{r} b_i ]

    对应的 (r) 的左右边界。

    区间最值可以用 ST表 维护。

    示例代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 200020;
    int n, a[maxn], b[maxn], fa[maxn][20], fb[maxn][20];
    void init() {
        for (int j = 0; (1<<j) <= n; j ++) {
            for (int i = 1; i+(1<<j)-1 <= n; i ++) {
                if (j == 0) fa[i][j] = a[i], fb[i][j] = b[i];
                else fa[i][j] = max(fa[i][j-1], fa[i+(1<<(j-1))][j-1]), fb[i][j] = min(fb[i][j-1], fb[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int calmax(int l, int r) {
        int m = r - l + 1;
        int j = log2(m);
        return max(fa[l][j], fa[r-(1<<j)+1][j]);
    }
    int calmin(int l, int r) {
        int m = r - l + 1;
        int j = log2(m);
        return min(fb[l][j], fb[r-(1<<j)+1][j]);
    }
    int get_first(int l) {
        int L = l, R = n, res = -1;
        while (L <= R) {
            int mid = (L + R) / 2;
            int v1 = calmax(l, mid), v2 = calmin(l, mid);
            if (v1 >= v2) {
                R = mid - 1;
                if (v1 == v2) res = mid;
            }
            else L = mid + 1;
        }
        return res;
    }
    int get_last(int l) {
        int L = l, R = n, res = -1;
        while (L <= R) {
            int mid = (L + R) / 2;
            int v1 = calmax(l, mid), v2 = calmin(l, mid);
            if (v1 <= v2) {
                L = mid + 1;
                if (v1 == v2) res = mid;
            }
            else R = mid - 1;
        }
        return res;
    }
    long long ans;
    void solve(int l) {
        int p1 = get_first(l), p2 = get_last(l);
        if (p1 != -1) ans += p2 - p1 + 1;
    }
    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);
        init();
        for (int l = 1; l <= n; l ++) solve(l);
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    SqlLite
    C# Sqlite 序列
    C#生成条形码 Code128算法
    【Ogre Beginner Guide】第二章 OGRE场景绘图
    【Ogre Beginner Guider】第一章 配置OGRE
    用户操作体验设计——小感触
    rails 调试
    mac下安装和使用brew
    如何使用 CCache 进行 Cocos2d-x 编译加速
    AndroidStudio使用和问题记录
  • 原文地址:https://www.cnblogs.com/quanjun/p/13849638.html
Copyright © 2011-2022 走看看