Submission #1254347

#TimeUsernameProblemLanguageResultExecution timeMemory
1254347TrendBattlesTriple Peaks (IOI25_triples)C++17
70.17 / 100
66 ms31408 KiB
#include "triples.h"
#include <bits/stdc++.h>
using namespace std;
using lli = int64_t;

const int BLOCK_SIZE = 600;

long long count_triples(vector <int> H) {
    int N = (int) H.size();

    lli ans = 0;
    for (int iter = 1; iter <= 2; ++iter) {
        for (int i = 0; i < N; ++i) {
            if (i < H[i]) continue;
            int p = i - H[i];

            if (H[p] >= H[i]) continue;

            ans += H[p + H[p]] == H[i] - H[p];

            if (H[i] != H[p] * 2) ans += H[i - H[p]] == H[i] - H[p];
        }

        reverse(H.begin(), H.end());
    }

    for (int i = 0; i < N; ++i) {
        if (i + H[i] >= N) continue;
        
        int j = i + H[i];
        if (H[j] > H[i] and j + H[j] - H[i] < N) ans += H[j + H[j] - H[i]] == H[j] - H[i];
    }

    //j - i = H[j] - H[i]
    //k - j = H[j] - H[k]
    vector <vector <int>> lft_side(2 * N + 1), rht_side(2 * N + 1);
    for (int i = 0; i < N; ++i) {
        lft_side[i - H[i] + N].push_back(i);
    }
    for (int i = N - 1; i >= 0; --i) {
        rht_side[i + H[i]].push_back(i);
    }

    //Small
    for (int delta = 0; delta <= 2 * N; ++delta) {
        vector <int>& list = lft_side[delta];
        if ((int) list.size() > BLOCK_SIZE) continue;

        int P = (int) list.size();
        for (int i = 0; i < P; ++i) {
            for (int j = i + 1; j < P; ++j) {
                int x = list[i], y = list[j];

                ans += x + H[y] < N and H[x + H[y]] == H[y] - H[x];
            }
        }
    }

    //Large
    //k - i = H[i] + H[k];
    for (int delta = 0; delta <= 2 * N; ++delta) {
        if ((int) lft_side[delta].size() <= BLOCK_SIZE) continue;

        vector <int> cnt(N + 1);

        for (int j : lft_side[delta]) {
            for (int k : rht_side[j + H[j]]) {
                if (k <= j) break;

                ans += k >= H[k] ? cnt[k - H[k]] : 0;
            }

            if (j + H[j] < N) cnt[j + H[j]] += 1;
        }
    }
    

    for (int i = 0; i < N; ++i) {
        if (H[i] % 2) continue;

        int half_len = H[i] / 2;
        ans -= i >= half_len and H[i - half_len] == half_len and i + half_len < N and H[i + half_len] == half_len;
    }


    return ans;
}

vector<int> construct_range(int M, int K) {
  return {1, 1, 2};
}
#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...