牛客多校2 - Greater and Greater(bitset优化暴力)

题目链接:点击查看

题目大意:给出一个长度为 n 的数组 a ,再给出一个长度最大为 m 的数组 b,现在问在 a 中所有长度为 m 的子数组中,有多少个子数组满足每个相应的元素都大于数组 b

题目分析:很显然的一个暴力时间复杂度是 n * m 级别的,高达 6e9 ,但是除以 32 后,时间复杂度好像就在可行范围内了,所以需要利用 bitset 优化一下

参考博客:https://www.cnblogs.com/whitelily/p/13311327.html

首先对于数组 b 的每个元素维护一个长度为 n 的bitset,假设 bit[ i ] 是 b[ i ] 所维护的的 bitset,bit[ i ][ j ] = 1 当且仅当 a[ j ] 大于等于 b[ i ]

不难看出,如果长度为 m 的 a 的一个子数组满足条件,需要满足 a[ i ] >= b[ j ] && a[ i + 1 ] >= b[ j + 1 ] && ... && a[ i + m - 1 ] >= b[ j + m - 1] ,换句话说需要 bit[ i ][ j ] = bit[ i + 1 ][ j + 1 ] = ... =  bit[ i + m - 1 ][ j + m - 1 ] = 1 同时成立,如果将 bit[ i ][ j ] 放在一个二维平面中去,显然上述条件涉及到的 m 个 bit 元素位于一条斜率为 1 的斜线上,换句话说,上述条件也等同于 bit[ i ][ j ] & bit[ i + 1 ][ j + 1 ] >> 1 & ... & bit[ i + m - 1 ][ j + m - 1 ] >> ( m - 1 ) 成立,这样在求出 bit 数组后, m 个 bit 数组进行 与 运算后 1 的个数就是答案了

但构造 bit 数组朴素的话需要 n * m 的时间复杂度,显然是不可以的,不难发现,如果 b[ i ] > b[ j ] ,当 bit[ j ] 已经转移完毕时,bit[ i ] 仅需要在 bit[ j ] 的基础上再转移就可以了,基于此,我们可以将数组 a 和数组 b 排序后双指针转移,这样时间复杂度就降低到了 O( n + m )

因为维护 m 个 bit 数组的 与 运算还是需要 n * m 的时间复杂度的,所以总的时间复杂度为 O(\frac{n*m}{w})

代码:
 

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=150000+100;

bitset<N>ans,t;

vector<pair<int,int>>a,b;
 
int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//	ios::sync_with_stdio(false);
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)
	{
		int num;
		scanf("%d",&num);
		a.emplace_back(num,i);
	}
	for(int i=0;i<m;i++)
	{
		int num;
		scanf("%d",&num);
		b.emplace_back(num,i);
	}
	sort(a.begin(),a.end());
	sort(b.begin(),b.end());
	int pos=n-1;
	ans.set();
	for(int i=m-1;i>=0;i--)
	{
		while(pos>=0&&a[pos].first>=b[i].first)
		{
			t.set(a[pos].second);
			pos--;
		}
		ans&=t>>b[i].second;
	}
	printf("%d\n",ans.count());










    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/107374295
今日推荐