zoukankan      html  css  js  c++  java
  • [CF689D] Friends and Subsequences

    [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;
    }
    
  • 相关阅读:
    冲刺(9)
    冲刺(8)
    冲刺(7)
    C#的post请求 捕获错误代码的内容
    [转载]Memory Limits for 32-bit and 64-bit processes
    IIS 503
    识别chrome浏览器
    时间同步
    修改Visual Studio启动画面授权信息
    Temporary ASP.NET Files权限问题
  • 原文地址:https://www.cnblogs.com/mollnn/p/14398822.html
Copyright © 2011-2022 走看看