Submission #1251262

#TimeUsernameProblemLanguageResultExecution timeMemory
1251262fafnirTriple Peaks (IOI25_triples)C++20
70 / 100
115 ms16200 KiB
#include <bits/stdc++.h>
using namespace std;

// #define LOCAL

// Part I
/*
    hi,hj,hk

    WLOG i < j < k

    Case work on which hi/hj/hk has largest value k-i

    Case 1: h[i] = k-i 
        *) Fixing i, fixes k
           -> k = i+h[i]
        *) Then
            hk = k-j or hk = j-i
            -> In both cases: j is fixed, 2*N possible triples


    Case 2: h[k] = k-i
        *) Fixing k, fixes i
            -> i = k-h[k]
        *) Now,
            h[i] = j-i or h[i] = k-j
            -> In both cases: j fixed, 2*N possible triples

    Case 3: h[j] = k-i
        *) If h[i] = j-i
          -> Fixing i, fixes j (h[i]+i = j)
          -> Then k = h[j]+i = k

        *) h[i] = k-j
           h[j] = k-i
           h[k] = j-i

           --> h[j]-h[i] = k-i-(k-j) = j-i
           --> h[j]-j = h[i]-i = c

           --> h[k] - h[j] = j - k
               h[k] + k = h[j] + j


        2D points/lines
        h[i] - i = 0
        [-N, N] -> [0,2*N]

        (i,h[i])
        (j,h[j])
        (k,h[k])

        Equations:
            i)      h[j] + j = h[k] + k
            ii)     h[j]-j   = h[i] - i


        
        For equation ii) --> O(n^2) solution
            -> If diagonal has size <= sqrt(n), then O(n) possible
            ->
                h[k]+k = h[j]+j = diag+j+j




*/

constexpr long long MUL = 200'001;
constexpr long long MULSQ = MUL * MUL;

long long chash(int i, int j, int k) {
    array<int,3> a{i,j,k};
    sort(a.begin(), a.end());
    long long h = a[0];
    h += MUL * a[1];
    h += MULSQ * a[2];
    return h;
}

bool check(int i, int j, int k, vector<int>& h) {
    if (min(i,min(j,k)) < 0 || max(i,max(j,k)) >= h.size()) {
        return false;
    }
    array<int,3> a{abs(j-i), abs(k-i), abs(k-j)};
    array<int,3> b{h[i],h[j],h[k]};
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());
    return a==b;
}

int count_triples(vector <int32_t> a){
    int n = a.size();
    int ans = 0;
    for (int i = 0; i < n; i++){
        if (i + a[i] < n){
            int j = i + a[i];
            if (a[j] < a[i]){
                int k = j - a[j];
                if (a[k] + a[j] == a[i]){
                    ans++;
                }
                
                if (2 * a[j] != a[i]){
                    k = i + a[j];
                    if (a[k] + a[j] == a[i]){
                        ans++;
                    }
                }
            }
        }
        
        if (i - a[i] >= 0){
            int j = i - a[i];
            if (a[j] < a[i]){
                int k = j + a[j];
                if (a[k] + a[j] == a[i]){
                    ans++;
                }
                
                if (2 * a[j] != a[i]){
                    k = i - a[j];
                    if (a[k] + a[j] == a[i]){
                        ans++;
                    }
                }
            }
        }
    }
    
    vector <int> b[2 * n + 1];
    for (int i = 0; i < n; i++){
        b[a[i] - i + n].push_back(i);
    }
    
    int cutoff = sqrt(n);
    
    for (int x = 1; x <= 2 * n; x++){
        if (b[x].size() <= cutoff){
            for (int v1 = 0; v1 < b[x].size(); v1++){
                int i = b[x][v1];
                for (int v2 = 0; v2 < v1; v2++){
                    int j = b[x][v2];
                    int k = j + a[i];
                    if (k < n && k > i){
                        if (a[i] == (k - j) && a[j] == (k - i) && a[k] == (i - j)){
                            ans++;
                        }
                    }
                }
            }
        } else {
            for (int k = 0; k < n; k++){
                int C = x - n;
                int sum = k - C;
                int diff = a[k];
                
                if (diff % 2 == sum % 2){
                    int i = (sum - diff) / 2;
                    int j = (sum + diff) / 2;
                    
                    if (0 <= i && i < n && 0 <= j && j < n && a[i] - i == C && a[j] - j == C){
                        ans++;
                    }
                }
            }
        }
    }
    
    for (int i = 0; i < n; i++){
        int j = i + a[i];
        if (j < n && a[j] > a[i]){
            int k = i + a[j];
            if (k < n){
                if (a[k] + a[i] == a[j] && a[k] != a[i]){
                    ans++;
                }
            }
        }
    }
    
    return ans;
}


std::vector<int> construct_range(int M, int K) {
    M = 0;
    K = 0;
    return {M,K};
}



#ifdef LOCAL
int32_t main() {

    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int tc;
    cin >> tc;

    while (tc--) {
        int n;
        cin >> n;

        vector<int> a(n);
        for (auto& e : a) cin >> e;

        cout << count_triples(a) << '\n';
    }


    return 0;
}
#endif
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...