Submission #1360194

#TimeUsernameProblemLanguageResultExecution timeMemory
1360194tickcrossyHieroglyphs (IOI24_hieroglyphs)C++20
19 / 100
83 ms25096 KiB
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

const int INF = 1e9;

struct SegTree {
    vector<int> tree;
    int n;
    SegTree(int size) {
        n = size;
        tree.assign(4 * n + 100, INF);
    }
    void update(int node, int start, int end, int idx, int val) {
        if(start == end) {
            tree[node] = val;
            return;
        }
        int mid = (start + end) / 2;
        if(idx <= mid) update(2 * node, start, mid, idx, val);
        else update(2 * node + 1, mid + 1, end, idx, val);
        tree[node] = min(tree[2 * node], tree[2 * node + 1]);
    }
    int query_all() {
        return tree[1];
    }
};

vector<int> ucs(vector<int> A, vector<int> B) {
    int n = A.size();
    int m = B.size();
    
    int max_v = 0;
    for(int v : A) max_v = max(max_v, v);
    for(int v : B) max_v = max(max_v, v);
    
    vector<vector<int>> posA(max_v + 1);
    vector<vector<int>> posB(max_v + 1);
    vector<int> ptrA(max_v + 1, 0);
    vector<int> ptrB(max_v + 1, 0);
    vector<int> k_val(max_v + 1, 0);
    vector<bool> is_cand(max_v + 1, false);
    vector<bool> in_affected(max_v + 1, false);
    
    for(int i = 0; i < n; ++i) posA[A[i]].push_back(i);
    for(int j = 0; j < m; ++j) posB[B[j]].push_back(j);
    
    long long L = 0;
    SegTree stA(max_v + 1), stB(max_v + 1);
    
    for(int x = 0; x <= max_v; ++x) {
        k_val[x] = min(posA[x].size(), posB[x].size());
        L += k_val[x];
        if (k_val[x] > 0) {
            stA.update(1, 0, max_v, x, posA[x][posA[x].size() - k_val[x]]);
            stB.update(1, 0, max_v, x, posB[x][posB[x].size() - k_val[x]]);
        }
    }
    
    if (L == 0) return {};
    
    auto nextA = [&](int y) {
        if (y <= max_v && ptrA[y] < posA[y].size()) return posA[y][ptrA[y]];
        return INF;
    };
    auto nextB = [&](int y) {
        if (y <= max_v && ptrB[y] < posB[y].size()) return posB[y][ptrB[y]];
        return INF;
    };
    
    int limitA = min(stA.query_all(), n - 1);
    int limitB = min(stB.query_all(), m - 1);
    
    vector<int> affected;
    auto add_affected = [&](int y) {
        if (!in_affected[y]) {
            affected.push_back(y);
            in_affected[y] = true;
        }
    };
    
    for(int i = 0; i <= limitA; ++i) {
        if (nextA(A[i]) == i) add_affected(A[i]);
    }
    for(int j = 0; j <= limitB; ++j) {
        if (nextB(B[j]) == j) add_affected(B[j]);
    }
    
    int num_cands = 0;
    vector<int> cand_list;
    
    auto check = [&](int y) {
        bool valid = (k_val[y] > 0) && (nextA(y) <= limitA) && (nextB(y) <= limitB);
        if (valid != is_cand[y]) {
            is_cand[y] = valid;
            if (valid) {
                num_cands++;
                cand_list.push_back(y);
            } else {
                num_cands--;
            }
        }
    };
    
    for(int y : affected) check(y);
    for(int y : affected) in_affected[y] = false;
    affected.clear();
    
    auto get_cand = [&]() {
        while(!cand_list.empty()) {
            int y = cand_list.back();
            if (is_cand[y]) return y;
            cand_list.pop_back();
        }
        return -1;
    };
    
    vector<int> U;
    int pA = 0, pB = 0;
    int old_limitA = limitA, old_limitB = limitB;
    
    while(L > 0) {
        if (num_cands != 1) return {-1};
        
        int x = get_cand();
        U.push_back(x);
        
        int new_pA = nextA(x) + 1;
        int new_pB = nextB(x) + 1;
        
        k_val[x]--;
        L--;
        
        if (k_val[x] == 0) {
            stA.update(1, 0, max_v, x, INF);
            stB.update(1, 0, max_v, x, INF);
        } else {
            stA.update(1, 0, max_v, x, posA[x][posA[x].size() - k_val[x]]);
            stB.update(1, 0, max_v, x, posB[x][posB[x].size() - k_val[x]]);
        }
        
        limitA = min(stA.query_all(), n - 1);
        limitB = min(stB.query_all(), m - 1);
        
        for(int i = pA; i < new_pA; ++i) {
            if (nextA(A[i]) == i) { ptrA[A[i]]++; add_affected(A[i]); }
        }
        for(int j = pB; j < new_pB; ++j) {
            if (nextB(B[j]) == j) { ptrB[B[j]]++; add_affected(B[j]); }
        }
        
        for(int i = max(new_pA, old_limitA + 1); i <= limitA; ++i) {
            if (nextA(A[i]) == i) add_affected(A[i]);
        }
        for(int j = max(new_pB, old_limitB + 1); j <= limitB; ++j) {
            if (nextB(B[j]) == j) add_affected(B[j]);
        }
        
        pA = new_pA; pB = new_pB;
        old_limitA = limitA; old_limitB = limitB;
        
        for(int y : affected) check(y);
        for(int y : affected) in_affected[y] = false;
        affected.clear();
    }
    
    return U;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...