Submission #1262832

#TimeUsernameProblemLanguageResultExecution timeMemory
1262832Canuc80kTriple Peaks (IOI25_triples)C++20
4.95 / 100
2096 ms11116 KiB
#include "bits/stdc++.h"
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;

ll res = 0;
map<string, ll> mm;

void add(string type, ll i, ll j, ll k) {
    mm[type] ++;
    cout << "--Spec: " << type << ' ' << i << ' ' << j << ' ' << k << endl;
    res ++;
}

long long countr(const vector<int> &a, const vector<int> &b) {
    int n = (int)a.size();
    int T = max(1, (int)std::sqrt((double)n));
    using ll = long long;

    // posA[v] = các chỉ số i có a[i] = v (tăng dần)
    unordered_map<int, vector<int>> posA;
    posA.reserve(n * 2);
    for (int i = 0; i < n; ++i) posA[a[i]].push_back(i);

    // posPair[(x,y)] = các chỉ số j có (a[j]=x, b[j]=y) (tăng dần)
    auto pack = [](int x, int y) -> uint64_t {
        return ( (uint64_t)(uint32_t)x << 32 ) | (uint32_t)y;
    };
    unordered_map<uint64_t, vector<int>> posPair;
    posPair.reserve(n * 2);
    for (int i = 0; i < n; ++i) posPair[pack(a[i], b[i])].push_back(i);

    // Đánh dấu heavy theo bậc của a=y
    vector<int> heavyY;
    heavyY.reserve(posA.size());
    unordered_set<int> isHeavy;
    isHeavy.reserve(posA.size() * 2);
    for (auto &p : posA) {
        if ((int)p.second.size() > T) {
            heavyY.push_back(p.first);
            isHeavy.insert(p.first);
        }
    }

    ll ans = 0;

    // ----- LIGHT: xử lý theo k, mỗi lần duyệt ≤ T chỉ số i và đếm j bằng binary search
    for (int k = 0; k < n; ++k) {
        int x = a[k], y = b[k];
        auto itY = posA.find(y);
        if (itY == posA.end()) continue;
        if (isHeavy.find(y) != isHeavy.end()) continue; // y nặng sẽ xử lý ở phần HEAVY

        const auto &Iy = itY->second; // các i có a[i] = y
        for (int t = 0; t < (int)Iy.size() && Iy[t] < k; ++t) {
            int i = Iy[t];
            uint64_t key = pack(x, b[i]);
            auto itPair = posPair.find(key);
            if (itPair == posPair.end()) continue;
            const auto &vec = itPair->second; // chỉ số j có (a[j]=x, b[j]=b[i])

            // Đếm j trong (i, k): i < j < k
            int L = int(upper_bound(vec.begin(), vec.end(), i) - vec.begin());
            int R = int(lower_bound(vec.begin(), vec.end(), k) - vec.begin());
            ans += (ll)(R - L);
        }
    }

    // ----- HEAVY: quét toàn mảng cho từng y nặng
    for (int y : heavyY) {
        // cntI[t] = số i đã thấy (i < hiện tại) với a[i]=y và b[i]=t
        unordered_map<int, int> cntI;
        cntI.reserve(T * 4);

        // P[x] = số cặp (i, j) đã tạo với i có a[i]=y, b[i]=b[j], j có a[j]=x (và i<j)
        unordered_map<int, long long> P;
        P.reserve(T * 8);

        for (int t = 0; t < n; ++t) {
            // 1) k = t (b[k] = y): cộng số cặp (i, j) có j < k, i < j
            if (b[t] == y) {
                auto itP = P.find(a[t]);
                if (itP != P.end()) ans += itP->second;
            }
            // 2) j = t: tạo cặp (i, j) với mọi i trước đó thỏa a[i]=y, b[i]=b[j]
            P[a[t]] += (long long)cntI[b[t]];
            // 3) i = t: thêm i vào kho với a[i]=y
            if (a[t] == y) cntI[b[t]]++;
        }
    }

    return ans;
}


long long count_triples(std::vector<int> H) {
    res = 0;
    // #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("A[k] Max: ", i, j1, k); if (j2 != -1 && j1 != j2) add("A[k] Max: ", 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("A[i] Max: ", i, j1, k); if (j2 != -1 && j1 != j2) add("A[i] Max: ", 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("A[j] Ma1: ", 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]) add("A[j] Ma2: ", i, j, k);
    // res += countr(a, b);

    for (auto [x, y]: mm) cout << x << ' ' << y << endl;  
    return res;
}

int rand(int l, int r) {
    static random_device rd;
    static mt19937 gen(rd());
    uniform_int_distribution<int> dist(l, r); 
    return dist(gen);
}

std::vector<int> construct_range(int M, int K) {
    vector<int> res;
    ll direction = 1, cur = 1;
    for (int i = 0; i + 3 < M; i += 3) {
        res.push_back(1);
        res.push_back(1);
        res.push_back(2);
        if (i + 3 >= M) {
            for (int j = i + 1; j < M; j ++)
                res.push_back(1);
        }
    }
    return res;
    // return {4,3,2,3,1,1,2,3,3,1,2,1,4,3,2,3,1,1,2,3};
    // return {1,4,3,4,3,1,1,2,3,3,1,2,1,4,3,2,3,1,1,2};
    // return {1,3,1,2,1,4,3,2,3,1};
}
#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...