Neev4321's blog

By Neev4321, history, 6 weeks ago, In English

I recently came across this blog post and decided to try some of its problems. I am stuck on this problem. I can think of a naive O(n^2) solution by iterating through all pairs but do not see any redundancy in this solution. I cannot see a way to make it sub-quadratic (other than using the fact that 1 ≤ ai ≤ 2.5 * 10^6, maybe?). Any hints would be appreciated.

  • Vote: I like it
  • +1
  • Vote: I do not like it

»
6 weeks ago, # |
  Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by Neev4321 (previous revision, new revision, compare).

»
6 weeks ago, # |
  Vote: I like it 0 Vote: I do not like it

Actually, $$$O(n^2)$$$ is intended, however, not in the way you might think. If I recall correctly, as soon as 4 pairs of the same sum are present, there is always a way to choose 4 different indices among them. For larger n, n^2 solution will end up finding the solution without checking all the pairs, which makes it $$$O(min(n^2, C))$$$, where $$$C$$$ is a large, but not enought to TLE number.

  • »
    »
    6 weeks ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Do you mean that I should randomize the pair selection? Because If one uses a deterministic strategy of going through all pairs and quitting early when a solution if found, you can always create a worst case scenario counter test where there is only a single quadruplet answer and one of the pairs of that quadruplet is the one that you consider last in your strategy.

    • »
      »
      »
      6 weeks ago, # ^ |
        Vote: I like it +3 Vote: I do not like it

      that will work good but think about it, in the worst case each pair gives you a different result but you have at most 5e6 possible sums of pairs so that means 5e6 sums to check so its still fast (im ignoring the fact that some of the equal pairs can have common elements but i think it changes the upper bound by not much)

      • »
        »
        »
        »
        6 weeks ago, # ^ |
          Vote: I like it 0 Vote: I do not like it

        I see now, thx. So, the bound on ai combined with the fact that "as soon as 4 pairs of the same sum are present, there is always a way to choose 4 different indices among them", gives an upper bound of 2 * 10^7.

»
6 weeks ago, # |
Rev. 3   Vote: I like it 0 Vote: I do not like it

after doing a lot of casework, youll be left with a case where all elements will be distinct. now run an (i,0,n)(j,i+1,n) loop some min(n^2, 5* 1e6 + 10) times. if a sum repeats nice. but in 5 * 1e6 iterations if you did not you can only have 5 * 1e6 distinct sums so pigeonhole or common sense any sum after these iterations is a repeat. keep in mind that if you encounter a sum twice, the previous sum indices [x, y] and currently [i, j] x < i && j < y always follows. (sorted distinct elements)

  • »
    »
    6 weeks ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Actually there is no need for casework to remove duplicates, you can incorporate duplicates into your main strategy. Here is my code.

    #include <bits/stdc++.h>
    using ll = long long;
    using ull = unsigned long long;
    using std::cin;
    using std::cout;
    using std::cerr;
    using std::pair;
    using std::array;
    using std::vector;
    using std::bitset;
    using std::deque;
    using std::queue;
    using std::string;
    using std::string_view;
    using std::priority_queue;
    using std::set;
    using std::map;
    using std::unordered_set;
    using std::unordered_map;
    using std::min;
    using std::max;
    using std::sort;
    /*
    handling of duplicates.
    if frequency >= 4, any 4 of them is the answer.
    otherwise, it only matters if the frequency is 1 or more than 1.
    */
    void preprocess_array(vector<pair<ll, ll>>& a, ll& n){
        sort (a.begin(), a.end());
        vector<pair<ll, ll>> b;
        for (ll i = 0; i < n;){
            ll orig = i, orig_val = a[i].first;
            while (i < n && a[i].first == orig_val) ++i;
            ll freq = i - orig;
            if (freq >= 4){
                cout << "YES\n";
                for (ll j = 0; j < 4; ++j)
                    cout << a[orig + j].second + 1 << ' ';
                std::exit(0);
            }
            b.emplace_back(orig_val, a[orig].second);
            if (freq > 1)
                b.emplace_back(orig_val, a[orig + 1].second);
        }
        a = std::move(b);
        n = a.size();
    }
    /*
    check if any two pairs have 4 distinct numbers.
    */
    void untangle (const vector<pair<ll, ll>>& occur){
        for (const auto& [i1, i2] : occur){
            for (const auto& [j1, j2] : occur){
                if (i1 != j1 && i1 != j2 && i2 != j1 && i2 != j2){
                    cout << "YES\n";
                    cout << i1 + 1 << ' ' << i2 + 1 << ' ';
                    cout << j1 + 1 << ' ' << j2 + 1 << ' ';
                    std::exit(0);
                }
            }
        }
    }
    static array<vector<pair<ll, ll>>, 5000001> pairs;
    int main() {
        std::ios::sync_with_stdio(false);
        cin.tie(nullptr);
        ll n;
        cin >> n;
        vector<pair<ll, ll>> a(n);
        for (ll i = 0; i < n; ++i){
            cin >> a[i].first;
            a[i].second = i;
        }
        preprocess_array(a, n);
        for (ll i = 0; i < n; ++i){
            for (ll j = i + 1; j < n; ++j){
                ll sum = a[i].first + a[j].first;
                pairs[sum].emplace_back(a[i].second, a[j].second);
                untangle(pairs[sum]);
            }
        }
        cout << "NO";
    }