题意: 给一个数组,问是否存在四个不相同的下标xywz使得 a x + a y = a z + a w a_x+a_y = a_z+a_w ax+ay=az+aw,输出任意一组xyzw就可以。
因为 a x a_x ax的范围是2.5e6,所以sum的范围是5e6,
- 看到网上很多说直接暴力然后对于每个和sum( s u m = a i + a j sum=a_i+a_j sum=ai+aj)存一下上一次达到sum的两个下标x,y,判断这ijxy是否构成一组解。不知道怎么证明正确性*
当有四组下标的和都为sum的时候,可以证明一定有解:(共8个下标
当有四个相同的下标,剩下四个下标构成一组解
当有三个相同的下标,剩下一组和这三组中任意一组构成一组解
当有两个相同的下标,剩下两组构成一组解
当没有相同的下标,输出任意两组
可以见代码(…
暴力枚举下标ij求他们的sum,复杂度上限是 O ( m i n ( 5 e 6 ∗ 3 + 1 , n 2 ) ) O(min(5e6*3+1, n^2)) O(min(5e6∗3+1,n2)), 1e7
前面的加了和是sum的达到4必定有解的判断,后面的只有是和前一种相同sum的比较四个下标是否都不相同(不知道为什么后面这种也能证明一定正确(》》
好像还可以用set做,相同的数达到两对就直接有解,所以可以转化为都不相同的情况
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
const int N = 2e5 + 10;
const int M = 5e6 + 10;
int a[N];
struct node {
int x, y;
};
vector<node> sum[M];
inline bool check(int x, int y, int z, int w) {
if (x != z && x != w && y != z && y != w) return 1;
return 0;
}
inline void getAns(int tot) {
cout << "YES\n";
map<int, int> mp;
for (int i = 0; i < 4; ++i) {
mp[sum[tot][i].x]++;
mp[sum[tot][i].y]++;
}
int op = -1, pos = -1;
for (auto x : mp) {
if (x.second > op) {
op = max(op, x.second);
pos = x.first;
}
}
if (op == 1) {
cout << sum[tot][0].x << " " << sum[tot][0].y << " "
<< sum[tot][1].x << " " << sum[tot][1].y << endl;
return;
}
if (op == 2) {
int cnt = 0;
for (int k = 0; k < 4; ++k) {
if (cnt >= 2) break;
if (sum[tot][k].x == pos || sum[tot][k].y == pos) continue;
cnt++;
cout << sum[tot][k].x << " " << sum[tot][k].y << " ";
}
}
if (op == 3) {
bool f = 0;
for (int k = 0; k < 4; ++k) {
if (sum[tot][k].x == pos && f || sum[tot][k].y == pos && f) continue;
if (sum[tot][k].x == pos || sum[tot][k].y == pos) f = 1;
cout << sum[tot][k].x << " " << sum[tot][k].y << " ";
}
}
if (op == 4) {
for (int k = 0; k < 4; ++k) {
if (sum[tot][k].x == pos) cout << sum[tot][k].y << " ";
else cout << sum[tot][k].x << " ";
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
// sort(a + 1, a + n + 1, [](int x, int y) { return x < y; });
for (int i = 1; i <= n; ++i) {
for (int j = i + 1; j <= n; ++j) {
int tot = a[i] + a[j];
sum[tot].push_back({i, j});
int siz = sum[tot].size();
if (siz >= 4) {
getAns(tot);
return 0;
}
if (siz > 1 && check(i, j, sum[tot][siz - 2].x, sum[tot][siz - 2].y)) {
cout << "YES\n";
cout << i << " " << j << " " << sum[tot][siz - 2].x << " " << sum[tot][siz - 2].y << endl;
return 0;
}
}
}
cout << "NO\n";
return 0;
}