G Greater and Greater

G Greater and Greater

Description
Given a sequence A of size n{n}n and a sequence B of size m, determine the number of subintervals(called S) of size m in A satisfying ∀i∈{1,2,⋯,m},Si≥Bi​.
Input
The first line contains two integers n,m (1≤n≤150000,1≤m≤min{n,40000}).
The second line contains n integers A1,A2,⋯,An (1≤Ai≤109), denoting the sequence A.
The third line contains n{n}n integers B1,B2,⋯,Bn (1≤Bi≤109), denoting the sequence B.
Output
Only one line containing one integer, denoting the answer.
Samples
Input 复制
6 3
1 4 2 8 5 7
2 3 3
Output
2
Hint
The two subintervals are [2,8,5],[8,5,7].
Source
2020牛客-2


题意:给你一个序列A,让你从A中找出一个些子串S,让串S对应位置Si上的元素大于等于Bi,问一共可以找出多少个这种的序列

思路:这是个考二进制的好题,第一步的转换就不好想。
首先判断A序列中的每个元素是否比B中的元素大,比B中的元素大即为一,否者为0

例如:
A:1 4 2 8 5 7
B:2 3 3
B[1] = 2 : 0 1 1 1 1 1
B[2] = 3 : 0 1 0 1 1 1
B[3] = 3 : 0 1 0 1 1 1

这一步转换就很妙了,因为我们可以发现只要有一条斜线全为1,那么此子串就是一个答案,但是我们这样求复杂度为O(n*m),我们可以将序列A,B排序,将复杂度降为O(n),我们从排序后的第一个数字开始算,那么如果比最大数字(B[1])还要大,那一定也比B[1]小的数字大
在这里插入图片描述

从此图可以看出(A[3],A[4],A[5])和(A[4],A[5],A[6])这两个串即为所求;
最后我们将每个数的二进制进行移位,具体操作如下:
B[1] = 2 : 0 1 1 1 1 1 左移零位
B[2] = 3 : 1 0 1 1 1 0 左移一位
B[3] = 3 : 0 1 1 1 0 0 左移两位
然后我们每一列都与1做&运算,最后看有几个一即可;

bitset:

bitset<N> test,tep;//创建N位的二进制位,默认值为零
test.set();//将所有位都置为一
test.set(i);//将第i位置为一
test.count();//1的个数
test&tep;//test与tep按位与
test<<i;//test左移i位,右面补零

Code:

#include<bits/stdc++.h>
#define bug(x) cout<<#x<<" = "<<x<<endl;
using namespace std;
typedef long long ll;
const int N = 1e5 + 5e4 +10;
const int inf = 1e9;
bitset<N>ans,bs;
vector<pair<int,int> >a,b;
int n,m,p;
bool cmp(pair<int,int> x,pair<int,int> y) {
	return x.first > y.first;
}
int main() {
	cin>>n>>m;
	int x;
	for(int i=0; i<n; i++) {
		cin>>x;
		a.push_back({x,i});
	}
	for(int i=0; i<m; i++) {
		cin>>x;
		b.push_back({x,i});
	}
	sort(a.begin(),a.end(),cmp);
	sort(b.begin(),b.end(),cmp);
	ans.set();
	int j = 0;
	for(int i=0; i<m; i++) {
		while(j<n&&a[j].first>=b[i].first) {
			bs.set(a[j].second);
			j++;
		}
//		for(int k=0;k<n;k++) cout<<bs[k]<<" ";
//		putchar('\n');
		ans&=bs>>b[i].second;
	}
	printf("%d",ans.count());
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值