zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第二场) G.Greater and Greater

    • 题意

      • 给出两个序列 A、B,其长度分别为 n、m,保证 $n>m $ ,求 A 中有多少个长度为 m 的子串 S,使得(forall iin{1,2,cdots,m},S_i ge B_i)
    • 解析

      • 出题人直播时表示看到数据很容易想到用 (bitset) (雾

      • 对于每一个 (A_i) 需要求一个长度为 (m)(bitset) (S_i) ,其中 (S_i[j] = 1) 表示 $A_i ge B_j $ 。

      • img

      • 那么如果得到了所有的 (S_i) 该如何判断答案呢

      • img

      • 可以发现只有某一列的三个数全为 1 ,才对答案有贡献。做法下面等会讲。

      • 现在我们要考虑的问题就是如何高效地得到所有地 (S_i)

      • 发现,在对 (B) 序列排序后,如果求出 (B) 对应的 (bitset) (S_j^‘),会发现 (i) 位置的 (bitset)(i-1)(bitset) 相比,只在第 (i) 大的数的对应位置上多了一个 1。

      • 我们现在对 (B) 也进行一次 (bitset) 操作,那么如果 (A[i]) 值在 ([B[j],B[j+1]))之间( (B) 排序后) ,那么可以求出 (S_i = S_j^‘)

      • 那么现在要求 (S_i) 只需要二分找到 (A[i])(B) 中的位置即可。

      • 在解决了 (S_i) 后要考虑如何得到答案,我们发现 (S_i)(S_{i-1}) 相比,只需要将 (S_{i-1}) 右移一位再进行 与 操作,就能把两者相联系起来,那么我们只要维护一个从起始开始的 与 的和 (ans),如果 (ans[0] = 1) 那么就对答案有贡献。

      • 注意要先处理好 (A) 中前 (m-1) 项,而且在 (ans) 的每次右移过程中需要将 (ans[m-1]) 赋值为 1。不然会影响到之后的判断。

    • 代码

      • #include <bits/stdc++.h>
        
        using namespace std;
        typedef long long ll;
        typedef pair<int,int> pii;
        const int Maxb = 10;
        const int Maxa = 2e5+10;
        const int Inf = 0x7f7f7f7f;
        const int Mod = 1e9+7;
        
        vector<pii> v;
        int a[Maxa],b[Maxb];
        bitset<Maxb> Bit[Maxb];
        
        int main(){
            int n,m;
            scanf("%d %d",&n,&m);
            for(int i=1;i<=n;i++)
                scanf("%d",a+i);
            v.push_back(make_pair(0,0));
            for(int i=1;i<=m;i++)
            {
                scanf("%d",b+i);
                v.push_back(make_pair(b[i],i));
            }
            sort(v.begin(),v.end());
            for(int i=1;i<=m;i++)
            {
                Bit[i] = Bit[i-1];
                Bit[i].set(m - v[i].second,1);
            }
            bitset<Maxb> ans;
            for(int i=1;i<m;i++)
            {
                pii cnt;
                cnt = make_pair(a[i],m+1);
                int t = lower_bound(v.begin(),v.end(),cnt) - v.begin() - 1;
                ans >>= 1;
                ans.set(m-1,1);
                ans &= Bit[t];
            }
            int Ans = 0;
            for(int i=m;i<=n;i++)
            {
                pii cnt;
                cnt = make_pair(a[i],m+1);
                int t = lower_bound(v.begin(),v.end(),cnt) - v.begin() - 1;
                ans >>= 1;
                ans.set(m-1,1);
                ans &= Bit[t];
                Ans += ans[0];
            }
            cout<<Ans<<endl;
            return 0;
        }
        
  • 相关阅读:
    基于Flask开发web微信
    爬取实例
    scrapy框架学习之路
    scripy
    wtforms
    由testcase数据之分析
    无用之flask学习
    无用之flask
    无用之学matplotlib,numpy,pandas
    jsp_1
  • 原文地址:https://www.cnblogs.com/HexQwQ/p/13296366.html
Copyright © 2011-2022 走看看