2020牛客暑期多校训练营(第二场)G
Greater and Greater
https://ac.nowcoder.com/acm/contest/5667/G
题目描述
  Given a sequence  of size 
 and a sequence 
 of size 
, determine the number of subintervals called 
 of size 
 in 
 satisfying 
, 
.  
输入描述
  The first line contains two integers  
,
 
. The second line contains 
 integers 
 
, denoting the sequence 
.
The third line contains  integers 
 
, denoting the sequence 
.  
输出描述
Only one line containing one integer, denoting the answer.
示例1
输入
6 3
1 4 2 8 5 7
2 3 3
输出
2
说明
  The two subintervals are .  
分析
  一道利用  的神题。
  对每一个  求一个长度为 
 的二进制串 
,
 当且仅当 
。
对于样例,可以构造三个二进制串:。设置一个 
 来代替二进制串,由于 
 由低位向高位存储,需要将上述二进制串镜像翻转,即 
;比如,
,
。对于一个合法区间,设其起点为 
,则 
;不妨将上述二进制串的向右平移,得到 
;对于同一列,为 
 与 
 至 
 与 
 的对应大小关系,当且仅当一列有 
 个 
 时,存在一个长度为 
 的合法区间。也就是说,将移动后的 
 个 
 进行与运算,最后得到的结果中 
 的个数即为答案;其中,第 
 个串右移 
 位。
  最暴力枚举获得  个 
 的时间复杂度为 
,显然是不可行的。不妨用 
pair<int,int> 记录 ,
 为数值,
 为元素在原序列中的位置,接着对 
 按数值降序排列。定义两个 
,用 
 记录与运算的最后结果(初始化为全 
);用 
 记录 
a[j].first>=b[i].first 时, 在原序列中的位置。接下来提到的 
 中的元素,都为排序后的序列中元素。枚举 
,接着枚举 
,若 
a[j].first>=b[i].first,那么令 cur.set(a[j].second);得到  后,将 
 右移 
b[i].second-1 位,同  进行与运算;多次迭代后,
ans.count()即为答案。事实上,经过排序后的序列,不必每次都从  开始枚举 
;当枚举 
 时,
 的数值必然比 
 的数值大,若 
a[j].first>=b[i-1].first,必定有 a[j].first>=b[i].first;也就是说,若满足a[j].first>=b[i-1].first的最大的  为 
,考察 
 时,直接从 
 开始枚举即可,上一次得到的 
 中的 
,在此次的考察中一定是正确的,对于 
,也是不遗漏的。    
/******************************************************************
Copyright: 11D_Beyonder All Rights Reserved
Author: 11D_Beyonder
Problem ID: 2020牛客暑期多校训练营(第二场) Problem G
Date: 8/5/2020
Description: To use bitset
*******************************************************************/
#include<iostream>
#include<bitset>
#include<utility>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=150004;
pair<int,int>a[N],b[N];
int n,m;
bitset<N>ans,cur;
int main()
{
    cin>>n>>m;
    int i,j;
    for(i=1;i<=n;i++) 
    {
        int x;
        scanf("%d",&x);
        a[i]=make_pair(x,i);
    }
    for(i=1;i<=m;i++)
    {
        int x;
        scanf("%d",&x);
        b[i]=make_pair(x,i);
    }
    //按数值降序
    sort(a+1,a+1+n,[](const pair<int,int>& x,const pair<int,int>& y){return x.first>y.first;});
    sort(b+1,b+1+m,[](const pair<int,int>& x,const pair<int,int>& y){return x.first>y.first;});
    //初始化
    ans.set();
    cur.reset();
    //枚举 b
    for(i=1,j=1;i<=m;i++)
    {
        //枚举 a
        //利用上次信息
        while(j<=n&&b[i].first<=a[j].first)
        {
            cur.set(a[j].second);
            j++;
        }
        //与运算
        ans&=cur>>b[i].second-1;
    }
    cout<<ans.count()<<endl;
    return 0;
} 收集牛客暑期多校训练营的题解
