zoukankan      html  css  js  c++  java
  • 20牛客多校 G Greater and Greater (思维)

    题目:传送门

    题意

    给一个长度为 n 的序列 A 和一个长度为 m 的序列 B,(m <= n),问你序列 A 中存在多少长度为 m 的子区间 [l, l + m - 1],满足 Al >= B1, Al+1 >= B2, .... ,Al+m-1 >= Bm;

    1 <= n <= 150000; 1 <= m <= min(n, 40000)

    思路

    参考:官方题解

    前置知识:需要会使用 bitset

    我们可以对每个 Ai 求一个 bitset Si, Si 的第 j 位为 1,则表示, Ai >= Bj;

    然后对每个 Ai 求一个 bitset res[i]; res[i] 的第 j 位为1,则表示 Ai >= Bj , Ai+1 >= Bj+1, Ai+2 >= Bj+2 .... Ai+m-j >= Bm;显然,当 res[i] 的第 1 位为 1 时,答案加 1

    可得递推式: res[i] = (res[i+1] >> 1) & Si

    如果 res[i + 1] 的第 j 位上为 1,则表示 Ai+1 >= Bj ...... Ai+m-j-1 >= Bm;那么 Ai 加入这个子区间,需要和 Bj-1 进行比较,即 res[i + 1] 第 j 位上的 1 向右移一位,然后和 si 按位与,如果 si 的第 j - 1 位为 1,意味着 Ai >= Bj-1,那么 res[i]第 j - 1 位上的 1 就能继承下去。

    考虑如何求 Si,我们可以对序列B排序,然后维护 m 个 bitset, 第 i 个 bitset 在 第 i - 1 个 bitset 的基础上在序列 B 第 i 大的数对应的位置多1.

    这样我们对每个 Ai 二分一下即可求 Si

    #include <bits/stdc++.h>
    #define LL long long
    #define ULL unsigned long long
    #define UI unsigned int
    #define mem(i, j) memset(i, j, sizeof(i))
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define pb push_back
    #define make make_pair
    #define INF 0x3f3f3f3f
    #define inf LLONG_MAX
    #define PI acos(-1)
    #define fir first
    #define sec second
    #define lb(x) ((x) & (-(x)))
    #define dbg(x) cout<<#x<<" = "<<x<<endl;
    using namespace std;
    
    const int N = 1e6 + 5, M = 4e4 + 5;
    
    const LL mod = 1e9 + 7;
    
    LL ksm(LL a, LL b) {
    
        LL res = 1LL;
    
        while(b) {
    
            if(b & 1) res = res * a % mod;
    
            a = a * a % mod;
    
            b >>= 1;
    
        }
    
        return res;
    
    }
    
    int n, a[N], id[M], b[M], m;
    
    bitset < M > res, s[M];
    
    int Fin(int x) {
    
        int ans = 1;
    
        int l = 0, r = m;
    
        while(l <= r) {
    
            int mid = (l + r) >> 1;
    
            if(b[id[mid]] > x) r = mid - 1;
    
            else {
    
                ans = mid;
    
                l = mid + 1;
    
            }
    
        }
    
        return ans;
    
    }
    
    void solve() {
    
        scanf("%d %d", &n, &m);
    
        rep(i, 1, n) scanf("%d", &a[i]);
    
        rep(i, 1, m) scanf("%d", &b[i]), id[i] = i;
    
        sort(id + 1, id + 1 + m, [](int A, int B) {
             return b[A] < b[B];
        });
    
        rep(i, 1, m) {
    
            s[i] = s[i - 1];
    
            s[i].set(id[i]);
    
        }
    
        int ans = 0;
    
        dep(i, 1, n) {
    
            res >>= 1;
    
            res &= s[Fin(a[i])];
    
            if(a[i] >= b[m]) res.set(m);
    
            ans += res[1];
    
        }
    
        printf("%d
    ", ans);
    
    }
    
    
    int main() {
    
    //    int _; scanf("%d", &_);
    //    while(_--) solve();
    
        solve();
    
        return 0;
    }
  • 相关阅读:
    软件杯_视频全量目标分析和建模_初步分析
    《一线架构师实践指南》第三部分阅读笔记
    eclipse配置Struts2至Tomcat8.5
    《一线架构师实践指南》阅读笔记02
    Java中对list集合使用HashSet去重不成功
    学习02
    《一线架构师实践指南》阅读笔记01
    通过DOS命令将txt文件导入mysql数据库
    zookeeper集群环境搭建详细图文教程
    SSO之CAS单点登录详细搭建教程
  • 原文地址:https://www.cnblogs.com/Willems/p/13303447.html
Copyright © 2011-2022 走看看