Greater and Greater
题目大意
给你一个长度分别为 n , m n,m n,m 的数字 a n , b n a_n ,b_n an,bn 问你能从数组 a a a 中选出多少长度为 m m m 的子串使其对应位置的值大于等于数组 b b b 的值
截图思路
这个题非常巧妙的用到了 b i t s e t bitset bitset 来进行处理我们拿样例了做个简单的演练
1
4
2
8
5
7
1\ 4 \ 2 \ 8 \ 5\ 7
1 4 2 8 5 7
2
3
3
2 \ 3 \ 3
2 3 3
我们做一个这样的除以,让
b
b
b 的值分别于数组
a
a
a 的进行比较大小,如果数组
a
a
a 的值大于等于
b
b
b 的值那么我们就令这个位置等于
1
1
1 否则为 0
2
:
0
1
1
1
1
1
2: \ 0 \ 1 \ 1 \ 1\ 1 \ 1
2: 0 1 1 1 1 1
3
:
0
1
0
1
1
1
3: \ 0 \ 1 \ 0 \ 1\ 1 \ 1
3: 0 1 0 1 1 1
3
:
0
1
0
1
1
1
3: \ 0 \ 1 \ 0 \ 1\ 1 \ 1
3: 0 1 0 1 1 1
我们可以发现如果让第
i
i
i 个数向前移动
i
−
1
i-1
i−1 位然后再进行一个 & 运算后这个数组里面 1 的个数刚好是答案。
之所以这样移动是因为数组
b
b
b 的第i个数字肯定不会和数组 a 的前 i-1 个元素进行比较,这样刚好去掉无效比较而且每一列刚好是从
a
i
a_i
ai开始的连续
m
m
m 个数字对的比较值,超级的妙!!!
知道这么多以后我们可以设置两个
b
i
t
s
e
t
bitset
bitset 数组一个作为答案,开始的时候全部赋值为 1 ,另一个用来记录 上面进行的比较,但是这里有个小优化就是,我们可以先把两个数组进行从大到小的排序,并且记录下标。
至于如何的比较就看看代码的
这里附加一个大佬的博客感觉写非常的好 点我查看
代码
#include<bits/stdc++.h>
using namespace std;
const int mx=160000;
int n,m;
struct node{
int x,id;
}a[mx],b[mx];
bool cmp(node a,node b){
return a.x>b.x;
}
bitset<mx>res,bit_m;
int main(){
ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i].x;a[i].id=i;
}
for(int i=1;i<=m;i++){
cin>>b[i].x;b[i].id=i;
}
sort(a+1,a+1+n,cmp);
sort(b+1,b+1+m,cmp);
res.set();//将 res 全部设置为 1
int p=1;
for(int i=1;i<=m;i++){
//开始比较对应位上的大小
while(p<=n&&a[p].x>=b[i].x){
//因为是从大到小排列的,如果 a 的数字大于 b 数组的数字,那么肯定
//大于 a 后面的所有位置的数字 所以这个位置对于b的这个位置以后的数字都是 1
bit_m.set(a[p++].id);
}
res&=(bit_m>>b[i].id-1);
}
cout<<res.count()<<"\n";
return 0;
}