码迷,mamicode.com
首页 > 其他好文 > 详细

[CF689D] Friends and Subsequences - 二分,ST表

时间:2021-02-16 12:01:53      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:sync   sub   ace   需要   names   min   ==   class   sign   

[CF689D] Friends and Subsequences - 二分,ST表

Description

给定两个长度均为 n 的数列,问有多少组 (l,r) 使得 max(al,...,ar)=min(bl,...,br)

Solution

固定左端点后,一个下降,一个上升,那么有效的区间一定是单调的

ST 表 + 二分即可

对于每个左端点需要二分两次,第一次找出第一个合法的右端点,第二次找出最后一个合法的右端点

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 200005;

int __log2[N];
int _log2(int x) { return __log2[x]; }
int _pre_log2()
{
    for (int i = 1; i < N; i++)
        __log2[i] = log2(i);
}

struct st
{
    int a[N][21];
    void build(int *src, int n)
    {
        for (int i = 1; i <= n; i++)
            a[i][0] = src[i];
        for (int i = 1; i <= 20; i++)
            for (int j = 1; j <= n - (1 << i) + 1; j++)
                a[j][i] = max(a[j][i - 1], a[j + (1 << (i - 1))][i - 1]);
    }
    int query(int l, int r)
    {
        int j = _log2(r - l + 1); // MAY BE ACCED
        return max(a[l][j], a[r - (1 << j) + 1][j]);
    }
} sta;

struct st_
{
    int a[N][21];
    void build(int *src, int n)
    {
        for (int i = 1; i <= n; i++)
            a[i][0] = src[i];
        for (int i = 1; i <= 20; i++)
            for (int j = 1; j <= n - (1 << i) + 1; j++)
                a[j][i] = min(a[j][i - 1], a[j + (1 << (i - 1))][i - 1]);
    }
    int query(int l, int r)
    {
        int j = _log2(r - l + 1); // MAY BE ACCED
        return min(a[l][j], a[r - (1 << j) + 1][j]);
    }
} stb;

int n, a[N], b[N];

signed main()
{
    ios::sync_with_stdio(false);
    _pre_log2();

    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i <= n; i++)
        cin >> b[i];

    sta.build(a, n);
    stb.build(b, n);

    int ans = 0;

    for (int i = 1; i <= n; i++)
    {
        int l = i, r = n, ans1 = 0;
        while (l <= r)
        {
            int mid = (l + r) / 2;
            if (sta.query(i, mid) == stb.query(i, mid))
                ans1 = mid;
            if (sta.query(i, mid) < stb.query(i, mid))
                l = mid + 1;
            else
                r = mid - 1;
        }
        int ans2 = 0;
        l = i, r = n;
        while (l <= r)
        {
            int mid = (l + r) / 2;
            if (sta.query(i, mid) == stb.query(i, mid))
                ans2 = mid;
            if (sta.query(i, mid) <= stb.query(i, mid))
                l = mid + 1;
            else
                r = mid - 1;
        }

        // cout << "i=" << i << "  " << ans1 << " " << ans2 << endl;
        // [ans1, ans2]
        if (ans1 && ans2)
        {
            ans += ans2 - ans1 + 1;
        }
    }

    cout << ans << endl;
}

[CF689D] Friends and Subsequences - 二分,ST表

标签:sync   sub   ace   需要   names   min   ==   class   sign   

原文地址:https://www.cnblogs.com/mollnn/p/14398822.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!