Submission #1262439

#TimeUsernameProblemLanguageResultExecution timeMemory
1262439Canuc80kTriple Peaks (IOI25_triples)C++20
25 / 100
174 ms84872 KiB
#include "bits/stdc++.h"
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;

ll res = 0;

void add(ll i, ll j, ll k) {res ++;}

ll countr(const vector<int> &a, const vector<int> &b) {
    int n = (int)a.size();
    int SQ = sqrt(n) + 1;
    ll res = 0;

    // Lưu vị trí các giá trị trong a và b
    unordered_map<int, vector<int>> posA, posB;
    for (int i = 0; i < n; i++) {
        posA[a[i]].push_back(i);
        posB[b[i]].push_back(i);
    }

    // Xác định heavy value trong a
    vector<int> heavy;
    for (auto &p : posA) {
        if ((int)p.second.size() > SQ) heavy.push_back(p.first);
    }

    // Tiền xử lý cho heavy: cnt[valA][valB] = số cặp (i) với a[i]=valA, b[i]=valB
    unordered_map<int, unordered_map<int,int>> cnt;
    for (int hv : heavy) {
        for (int idx : posA[hv]) {
            cnt[hv][b[idx]]++;
        }
    }

    // Đếm số j thỏa điều kiện prefix để xử lý light
    unordered_map<int, unordered_map<int,int>> seen; 
    // seen[valA][valB] = số j đã đi qua với a[j]=valA, b[j]=valB

    for (int k = 0; k < n; k++) {
        int x = a[k]; // cần a[j] = a[k] = x
        int y = b[k]; // cần a[i] = b[k] = y

        // Heavy: dùng cnt precompute
        if (posA[x].size() > SQ) {
            if (cnt[x].count(y)) res += cnt[x][y];
        } 
        // Light: duyệt hết các i ứng với a[i] = y
        else {
            for (int i : posA[y]) if (i < k) {
                int val = b[i];
                if (seen[x].count(val)) res += seen[x][val];
            }
        }

        // update seen cho j = k
        seen[a[k]][b[k]]++;
    }

    return res;
}


long long count_triples(std::vector<int> H) {
    // #TH: a[k] max
    for (int k = 2; k < H.size(); k ++) {
        int i = k - H[k]; if (i < 0 || H[i] >= H[k]) continue; int j1 = k - H[i], j2 = i + H[i];
        if (j1 < 0 || H[j1] >= H[k] || H[j1] != j1 - i) j1 = -1;
        if (j2 >= k || H[j2] >= H[k] || H[j2] != k - j2) j2 = -1;
        if (j1 != -1) add(i, j1, k); if (j2 != -1 && j1 != j2) add(i, j2, k);
    }

    // #TH: a[i] max
    for (int i = 0; i + 2 < H.size(); i ++) {
        int k = i + H[i]; if (k >= H.size() || H[k] >= H[i]) continue; int j1 = k - H[k], j2 = i + H[k];
        if (j1 < 0 || H[j1] >= H[i] || H[j1] != j1 - i) j1 = -1;
        if (j2 >= k || H[j2] >= H[i] || H[j2] != k - j2) j2 = -1;
        if (j1 != -1) add(i, j1, k); if (j2 != -1 && j1 != j2) add(i, j2, k);
    }
    
    // #TH: a[j] max, j - i = a[i]
    for (int i = 0; i + 2 < H.size(); i ++) {
        int j = i + H[i]; if (j >= H.size() || H[j] <= H[i]) continue; int k = i + H[j];
        if (k >= H.size() || H[k] >= H[j] || k - H[k] != j || k - j == H[i]) k = -1;
        if (k != -1) add(i, j, k);
    }

    // #TH: a[j] max, j - i = a[k]
    // for (int i = 0; i + 2 < H.size(); i ++) {
    //     for (int k = i + H[i] + 1; k < H.size(); k ++) {
    //         int j = i + H[k]; if (j != k - H[i] || j >= H.size()) continue;
    //         if (H[i] >= H[j] || H[j] <= H[k] || k - i != H[j] || j >= k) continue;
    //         // cout << "OKE: " << i << ' ' << j << ' ' << k << endl;
    //         add(i, j, k);
    //     }
    // }

    vector<int> a, b;
    for (int i = 0; i < H.size(); i ++) a.push_back(H[i] + i);
    for (int i = 0; i < H.size(); i ++) b.push_back(i - H[i]);
    
    // for (int i = 0; i < a.size(); i ++)
    //     for (int j = i + 1; j < a.size(); j ++)
    //         for (int k = j + 1; k < a.size(); k ++)
    //             if (a[i] == b[k] && a[j] == a[k] && b[i] == b[j]) res ++;
    res += countr(a, b);
    return res;
}

std::vector<int> construct_range(int M, int K) {
    // vector<int> res; res.push_back(1);
    // for (int i = 1; i < M; i ++) res.push_back(i);
    // return res;
}

Compilation message (stderr)

triples.cpp: In function 'std::vector<int> construct_range(int, int)':
triples.cpp:115:1: warning: no return statement in function returning non-void [-Wreturn-type]
  115 | }
      | ^
#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...