https://ac.nowcoder.com/acm/contest/33195/I
题意
给定两个数列 a[] 和 b[],问:
- 是否 a [ ] a[] a[] 中存在两个位置 i , j ( i ≠ j ) i, j\ (i \neq j) i,j (i=j), b [ ] b[] b[] 中存在两个位置 k , l ( k ≠ l ) k,l\ (k \neq l) k,l (k=l),满足: ∣ a i − a j ∣ = ∣ b k − b l ∣ \left|a_i-a_j\right|=\left|b_k-b_l\right| ∣ai−aj∣=∣bk−bl∣ ?
如果存在,分别输出四个位置,否则输出 -1。
2 ≤ n , m ≤ 1 0 6 , 0 ≤ a i , b i ≤ 1 0 7 2≤n,m≤10^6,\ 0≤a_i,b_i≤10^7 2≤n,m≤106, 0≤ai,bi≤107
思路
不考虑先后位置,也就是使
a
i
−
a
j
=
b
k
−
b
l
a_i - a_j = b_k - b_l
ai−aj=bk−bl,即
a
i
+
b
l
=
a
j
+
b
k
a_i + b_l = a_j + b_k
ai+bl=aj+bk。
观察到 ai 和 bi 的范围,得知 ai + bl 的范围为 [0, 2e7]。
如果 a[] 中元素各不相同,并且 b[] 中元素各不相同,那么由鸽巢原理,如果遍历 2e7+1 个两数之和 ai + bl,那么一定有两个是相同的,这两个相同的便是满足的。
所以我们把两个数组分别去重,然后两重循环,最多遍历 2e7+1 次就能找到相同值,将其位置输出即可。
但是需要提前考虑去重之前就满足的情况:如果 a 数组中有两个数相同,并且 b 数组中有两个数相同,也是满足的。
Code
#include<bits/stdc++.h>
using namespace std;
#define Ios ios::sync_with_stdio(false),cin.tie(0)
#define endl '\n'
const int N = 1000010, mod = 1e9+7;
int T, n, m;
int a[N], b[N];
int cnta[N*10], cntb[N*10];
int ta[N], tb[N];
int mp[N*20][4];
int mpa[N*10], mpb[N*10];
signed main(){
scanf("%d%d", &n, &m);
int flag1 = -1, flag2 = -1;
for(int i=1;i<=n;i++){
scanf("%d", &a[i]);
cnta[a[i]] ++;
if(cnta[a[i]] >= 2) flag1 = a[i];
mpa[a[i]] = i;
}
for(int i=1;i<=m;i++){
scanf("%d", &b[i]);
cntb[b[i]] ++;
if(cntb[b[i]] >= 2) flag2 = b[i];
mpb[b[i]] = i;
}
if(flag1 != -1 && flag2 != -1)
{
int cnt = 0;
for(int i=1;i<=n;i++){
if(a[i] == flag1 && cnt < 2) cout << i << ' ', cnt ++;
}
cnt = 0;
for(int i=1;i<=m;i++){
if(b[i] == flag2 && cnt < 2) cout << i << ' ', cnt ++;
}
return 0;
}
sort(a+1, a+n+1);
sort(b+1, b+m+1);
int idx1 = 0, idx2 = 0;
for(int i=1;i<=n;i++)
{
if(i == 1 || a[i] != a[i-1]) ta[++idx1] = a[i];
}
for(int i=1;i<=m;i++)
{
if(i == 1 || b[i] != b[i-1]) tb[++idx2] = b[i];
}
for(int i=0;i<=2e7;i++) mp[i][0] = -1;
int flag = -1;
for(int i=1;i<=idx1;i++)
{
for(int j=1;j<=idx2;j++)
{
int sum = ta[i] + tb[j];
if(mp[sum][0] != -1){
flag = sum;
mp[sum][2] = ta[i], mp[sum][3] = tb[j];
break;
}
mp[sum][0] = ta[i], mp[sum][1] = tb[j];
}
if(flag != -1) break;
}
if(flag != -1)
cout << mpa[mp[flag][0]] << " " << mpa[mp[flag][2]] << " " << mpb[mp[flag][1]] << " " << mpb[mp[flag][3]];
else cout << -1;
return 0;
}
终于把牛客多校补完了,要及时回顾复习啊!