2022牛客多校10 I-Yet Another FFT Problem?(鸽巢原理)

 

题目大意:给定一个n,m,分别代表a数组和b数组的长度,接下来给出a数组和b数组,问是否存在i,j,k,l满足1<=i,j<=n,1<=k,l<=m,i!=j,k!=l使得|aj-ai|=|bl-bk|,如果存在则输出,否则输出-1.

解题思路:由|aj-ai|=|bl-bk|交换左右两边可以去掉绝对值得到aj+bk=bl+ai,又因为0<=ai,bi<=1e7,所以我们可以开长度为2e7的数组作为map映射a,b两个数组中每个值的位置,以及两个数的加和==temp时两个数字ai和bl,在两个数组中分别出现的位置,具体的做法就是遍历a,b两个数组中所有不同的数字,并记录两个数的加和,如果两个数的加和在之前已经出现过,那么答案就是当前两个数的位置和之前出现相同加和时两个数的位置,这里我们需要注意一点就是a,b两个数组必须去重之后才能遍历两个数组找加和,因为如果不去重的话两个数组的长度都是1e6两重循环会超时的,但是由于我们去重了,所以两个数的加和最多有2e7种情况,所以复杂度就不会超了,但是我们还要考虑到一种情况就是在a,b两个数组中可能会有ai=aj,bl=bk,所以在去重之前我们要特判一下这种情况。最后也是说一点注意事项,前面说到要用数组来模拟map的功能,主要是因为map会比数组要慢,我一开始就是用的map结果超时了,但是改成数组之后就过了。

上代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
const int N=2e7+10;
int n,m,a[N],b[N];
int mpa1[N],mpa2[N],mpb1[N],mpb2[N],mp[N];
vector<int>ca,cb;
int main()
{
	scanf("%d %d",&n,&m);
	int posa1=0,posa2=0,posb1=0,posb2=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		if(mpa1[a[i]])
		{
			posa1=mpa1[a[i]];
			posa2=i;
		}
		else
		{
			mpa1[a[i]]=i;
			ca.push_back(a[i]);
		}
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&b[i]);
		if(mpb1[b[i]])
		{
			posb1=mpb1[b[i]];
			posb2=i;
		}
		else
		{
			mpb1[b[i]]=i;
			cb.push_back(b[i]);
		}	
	}
	sort(ca.begin(),ca.end());
	sort(cb.begin(),cb.end());
	ca.erase(unique(ca.begin(),ca.end()),ca.end());
	cb.erase(unique(cb.begin(),cb.end()),cb.end());
	if(posa1&&posb1)
	{
		cout<<posa1<<" "<<posa2<<" "<<posb1<<" "<<posb2<<endl;
		return 0;
	}
	int flag=0;
	for(int i=0;i<ca.size();i++)
		for(int j=0;j<cb.size();j++)
		{
			int temp=ca[i]+cb[j];
			if(mpa2[temp])
			{
				cout<<mpa1[ca[i]]<<" "<<mpa2[temp]<<" "<<mpb1[cb[j]]<<" "<<mpb2[temp];
				flag=1;
				return 0;	
			}
			mpa2[temp]=mpa1[ca[i]];
			mpb2[temp]=mpb1[cb[j]];
		}
		if(flag==0)
		cout<<"-1"<<endl;
		return 0;
 } 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值