“蔚来杯“2022牛客暑期多校训练营10 Yet Another FFT Problem?

该博客主要介绍了如何解决一道算法竞赛题目,题目要求找到两个整数序列A和B中是否存在不同的元素对(i, j)和(k, l),使得|a_i - a_j| = |b_k - b_l|。通过转化问题为寻找相同的和ai+b_l与aj+b_k,利用鸽巢原理简化问题,并通过去重和枚举实现算法。最终,当找到满足条件的元素对时输出,否则输出-1。
摘要由CSDN通过智能技术生成

原题题面:https://ac.nowcoder.com/acm/contest/33195/I

题目大意:
给定两个整数序列 A = [ a 1 , a 2 … a n ] , B = [ b 1 , b 2 … , b m ] A=[a_1,a_2…a_n],B=[b_1,b_2…,b_m] A=[a1,a2an],B=[b1,b2,bm],求是否存在不同的 1 < = i , j < = n 1<=i,j<=n 1<=i,j<=n, 1 < = k , l < = m 1<=k,l<=m 1<=k,l<=m,满足 ∣ a i − a j ∣ = ∣ b k − b l ∣ |a_i-a_j|=|b_k-b_l| aiaj=bkbl

分析:
可先将 ∣ a i − a j ∣ = ∣ b k − b l ∣ |a_i-a_j|=|b_k-b_l| aiaj=bkbl转化为 a i + b l = a j + b k a_i+b_l=a_j+b_k ai+bl=aj+bk,所以题目就变成了找是否有 a i + b l a_i+b_l ai+bl的和相同
再读题目,注意到 a i , b i a_i,b_i ai,bi的值均不大于 1 0 7 10^7 107,由于鸽巢原理,其和必定在 V ( 2 ∗ 1 0 7 ) V(2*10^7) V(2107)次的计算后有重复 ( a 数组内的值均不相同且 b 数组内的值均不相同 ) (a数组内的值均不相同且b数组内的值均不相同) (a数组内的值均不相同且b数组内的值均不相同)
所以可以去重,再枚举计算

代码:

#include<bits/stdc++.h>
#define LL long long
#define debug  -1
using namespace std;

const int max_len=1e6+7;
const int max_val=1e7+7;
const int max_val_with_2=2e7+10;
int a[max_len],b[max_len];


struct Node{
	int id[3],val;
};
Node mp[max_val_with_2];
int dx[max_val],dy[max_val];
int idx[max_len],idy[max_len];
template<class T> inline void read(T&x){
	char ch,last=' ';
	while(!isdigit(ch=getchar())) last=ch;
	x=ch^48;
	while(isdigit(ch=getchar())) x=(x<<3)+(x<<1)+(ch^48);
	if(last=='-') x=-x;
}
int main(){
	int n,m,x,cnt,fx1,fx2,fy1,fy2,cnta,cntb;
	cnta=cntb=0;
	fx1=fx2=fy1=fy2=0;
	read(n); read(m);
	for(int i=1;i<=n;i++){
		read(x);
		if(!dx[x]){
			a[++cnta]=x; dx[x]=i; idx[cnta]=i;
		}else{
			fx1=i; fx2=dx[x];
		}
	}
	for(int i=1;i<=m;i++){
		read(x);
		if(!dy[x]){
			b[++cntb]=x; dy[x]=i; idy[cntb]=i;
		}else{
			fy1=i; fy2=dy[x];
		}
	}
	if(fy1&&fy2&&fx1&&fx2){
		printf("%d %d %d %d\n",fx1,fx2,fy1,fy2);
	    return 0;
	}else{
		for(int i=1;i<=cnta;i++){
		    for(int j=1;j<=cntb;j++){
			   cnt++;
			   if(cnt>2*max_val){
				   printf("-1\n");
				   return 0;
			   }
			   x=a[i]+b[j];
			   if(mp[x].val){
			   	  mp[x].val++;
			   	  printf("%d %d %d %d\n",idx[i],mp[x].id[1],idy[j],mp[x].id[2]);
			   	  return 0;
			   }else{
			   	mp[x].val++;
			   	mp[x].id[1]=idx[i];
			   	mp[x].id[2]=idy[j];
			   }
		    }
	    }
	}
	
	printf("-1\n");
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值