Codeforces Round #707 (Div. 2, based on Moscow Open Olympiad in Informatics) C
Codeforces Round #707 (Div. 2, based on Moscow Open Olympiad in Informatics) C
大意
给定一个数组 \(a\) ,保证 \(n \leq 200000\) , \(1 \leq a_i \leq 2.5*10^6\)
问:
是否存在四个各不相同的数 \(x,y,z,w\) ,满足 \(a_x+a_y = a_z + a_w\)
存在输出YES,接下来输出任意一组解
否则输出NO
思路
没注意 \(a_i\) 的范围...
考虑等式变形 \(a_x-a_z=a_w-a_y\)
可以证明,如果有解,必定有一组可行解满足 \(max(x, z) < min(w, y)\)
换种说法,就是选择的数代表的两个区间 \([min(x,z), max(x,z)]\) , \([min(w,y), max(w,y)]\) 不重叠
证明只需要依据原数组构造差分数组,这样容易发现,如果重叠,重叠的部分是完全可以删掉的。
所以,我们得到了一个时间复杂度为 \(\Theta(min(N^2, N+max(a_i)))\) 的算法。
枚举 \(x,z\) ,记录 \(\mid a_x-a_z \mid\) 的值对应的 \(x, z\) ,这里,如果值不存在,记录下来。
如果值存在,且满足题意,那么说明我们已经找到了一组可行解,如果不满足题意,那么,根据上述,应该保留 \(max(x,z)\) 更小的一组数据。
最后的答案中,区间可能重叠,上述证明是为了说明保留 \(max(x,z)\) 更小数据的正确性。
代码中,为了保证可行解满足上述,我们可以从大到小枚举j,这样保证找到的j一定是单调递减的。
因为 \(a_i > 0\) , 所以不存在两次i不相等,j相等但结果相等的情况。
同理不存在两次i相等,j不相等但结果相等的情况。
代码
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define ull unsigned long long
#define cint const int&
#define Pi acos(-1)
const int mod = 1e9+7;
const int inf_int = 0x7fffffff;
const ll inf_ll = 0x7fffffffffffffff;
const double ept = 1e-9;
int n;
int a[200200];
int mp[2500010];
int q[2500001][2], cnt;
int ans[4];
int main() {
ios::sync_with_stdio(false);
cin >> n;
for(int i=1; i<=n; i++) cin >> a[i];
for(int i=1; i<=n && !ans[0]; i++)
for(int j=n; j>i && !ans[0]; j--) {
int r = a[j] - a[i];
if(mp[abs(r)]) {
int e = mp[abs(r)];
if(q[e][0] != i && q[e][1] != j && q[e][1] != i) {
ans[0] = q[e][0];
ans[1] = q[e][1];
ans[2] = i;
ans[3] = j;
break;
}
} else {
q[++cnt][0] = i, q[cnt][1] = j;
mp[abs(r)] = cnt;
}
}
if(!ans[0]) cout << "NO" << endl;
else {
cout << "YES" << endl;
if((a[ans[0]] - a[ans[1]]) != (a[ans[2]] - a[ans[3]])) swap(ans[0], ans[1]);
cout << ans[0] << ' ' << ans[3] << ' ' << ans[1] << ' ' << ans[2] << endl;
cout << endl;
}
return 0;
}

浙公网安备 33010602011771号