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; }
收集牛客暑期多校训练营的题解