Codeforces Round #707 C. Going Home

C. Going Home

题意

n ( 1 ≤ n ≤ 2 ⋅ 1 0 5 ) n(1\le n \le 2\cdot 10^5) n(1n2105) 个数,每个数 1 ≤ a i ≤ 2.5 ⋅ 1 0 6 1\le a_i \le 2.5\cdot 10^6 1ai2.5106 ,要求找到四个不同的数 x , y , z , w x,y,z,w x,y,z,w ,使得 a x + a y = a z + a w a_x+a_y=a_z+a_w ax+ay=az+aw 。不能找到则输出 NO

题解

  • 注意到 a i a_i ai 的范围为 1 ≤ a i ≤ 2.5 ⋅ 1 0 6 1\le a_i \le 2.5\cdot 10^6 1ai2.5106 ,可以先找两个数的和为某个值的所有组合,即 v [ x ] v[x] v[x] 存储所有和为 x x x 的一对下标,但是要求四个下标都不同,所以可能找到很多无效的下标对。这样的复杂度为 O ( C ⋅ n 2 ) O(C\cdot n^2) O(Cn2) C C C 表示有相同下标的下标对个数。
  • 为了减少无效的下标对个数,可以先做预处理。记录每一个值出现的所有位置,如果一个值出现了 4 4 4 次,那么这四个位置就是答案。如果有两个值都出现了两次,那么这四个位置也可以是答案。那么剩下的情况最多有一对数出现超过两次,其他的数各不相同。也就是最多找到一次无效的答案。这样就复杂度变为 O ( n 2 ) O(n^2) O(n2)
  • 两个数的和的值域为 [ 2 , 5 e 6 ] [2,5e6] [2,5e6],那么找大约 5 e 6 5e6 5e6 次一定可以找到答案,复杂度为 O ( m i n ( n 2 , 5 e 6 ) ) O(min(n^2,5e6)) O(min(n2,5e6))

代码

#pragma region
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define per(i, a, n) for (int i = n; i >= a; --i)
#pragma endregion
const int maxn = 2e5 + 5;
vector<pair<int, int>> v[int(5e6) + 5];
vector<int> pos[int(5e6) + 5];
int a[maxn];
int main() {
    
    
    int n;
    scanf("%d", &n);
    int c = 0;
    rep(i, 1, n) {
    
    
        scanf("%d", &a[i]);
        pos[a[i]].push_back(i);
        if (pos[a[i]].size() == 4) {
    
    
            puts("YES");
            for (auto it : pos[a[i]]) printf("%d ", it);
            return 0;
        }
        if (pos[a[i]].size() == 2) {
    
    
            if (c) {
    
    
                puts("YES");
                printf("%d %d %d %d\n", pos[c][0], pos[a[i]][0], pos[c][1], pos[a[i]][1]);
                return 0;
            }
            c = a[i];
        }
    }
    rep(i, 1, n) rep(j, i + 1, n) {
    
    
        for (auto it : v[a[i] + a[j]]) {
    
    
            set<int> st;
            st.insert(i), st.insert(j), st.insert(it.first), st.insert(it.second);
            if (st.size() == 4) {
    
    
                printf("YES\n%d %d %d %d\n", i, j, it.first, it.second);
                return 0;
            }
        }
        v[a[i] + a[j]].push_back({
    
    i, j});
    }
    puts("NO");
}

猜你喜欢

转载自blog.csdn.net/weixin_43860866/article/details/114991318