Submission #860363


Source Code Expand

#include <iostream>
#include <vector>
#include <algorithm>
#include <array>
#include <functional>
#include <memory>
#include <cmath>
#include <cassert>
#define repeat(i,n) for (int i = 0; (i) < (n); ++(i))
using namespace std;
 
template <class T>
struct persistent_array { // fully persistent
    static const int SHIFT_SIZE = 3; // log of the branching factor b
    // int size = 0; // the size n
    int shift = -1;
    // array<shared_ptr<persistent_array>, (1 << SHIFT_SIZE)> children; // smart pointers are slow...
    persistent_array *children[1 << SHIFT_SIZE] = {};
    T leaf = {};
    persistent_array(persistent_array const &) = default; // O(b)
    persistent_array() = default;
    persistent_array(int size) { // O(n \log_b n + m b \log_b n) for number of update m
        // size = a_size;
        if (size == 0) return;
        for (shift = 0; (1 << (shift * SHIFT_SIZE)) < size; ++ shift);
        shift = shift ? (shift - 1) * SHIFT_SIZE : -1;
    }
    inline T const & get(int i) const { // O(log_b n)
        return const_cast<persistent_array *>(this)->unsafe_get(i);
    }
    T & unsafe_get(int i) {
        if (shift == -1) return leaf;
        return children[index_high(i)]->unsafe_get(index_low(i));
    }
    T & set(int i) { // O(b log_b n), increment m
        if (shift == -1) return leaf;
        auto & p = children[index_high(i)];
        p = p ? new persistent_array(*p) : new persistent_array(child_size());
        return p->set(index_low(i));
    }
    inline int index_high(int index) const { return index >> shift; }
    inline int index_low (int index) const { return index & ((1 << shift) - 1); }
    inline int child_size()          const { return 1 << shift; }
    persistent_array deepcopy() const {
        persistent_array that;
        // that.size  = this->size;
        that.shift = this->shift;
        that.leaf  = this->leaf;
        repeat (i, 1 << SHIFT_SIZE) if (this->children[i]) that.children[i] = new persistent_array(this->children[i]->deepcopy());
        return that;
    }
};
 
struct persistent_disjoint_sets {
    persistent_array<int> xs;
    persistent_disjoint_sets() = default;
    explicit persistent_disjoint_sets(size_t n) : xs(n) { repeat (i,n) xs.set(i) = -1; }
    bool is_root(int i) { return xs.get(i) < 0; }
    int find_root(int i) { int j = xs.get(i); return j < 0 ? i : find_root(j); } // don't memoize
    // int find_root(int i) { return is_root(i) ? i : xs.set(i) = find_root(xs.get(i)); }
    int unsafe_find_root(int i) { return is_root(i) ? i : xs.unsafe_get(i) = find_root(xs.get(i)); }
    int set_size(int i) { return - xs.get(find_root(i)); }
    int union_sets(int i, int j) {
        i = find_root(i); j = find_root(j);
        if (i != j) {
            if (set_size(i) < set_size(j)) swap(i,j);
            int *x_i = &xs.set(i);
            int *x_j = &xs.set(j);
            *x_i += *x_j;
            *x_j = i;
        }
        return i;
    }
    bool is_same(int i, int j) { return find_root(i) == find_root(j); }
    persistent_disjoint_sets deepcopy() {
        persistent_disjoint_sets that;
        that.xs = this->xs.deepcopy();
        return that;
    }
    inline int query(int x, int y) {
        x = find_root(x);
        y = find_root(y);
        return x == y ? set_size(x) : set_size(x) + set_size(y);
    };
};
 
int main() {
    // input
    int n, m; scanf("%d%d", &n, &m);
    vector<int> a(m), b(m);
    repeat (e,m) {
        scanf("%d%d", &a[e], &b[e]);
        -- a[e]; -- b[e];
    }
    int q; scanf("%d", &q);
    vector<int> x(q), y(q), z(q);
    repeat (i,q) {
        scanf("%d%d%d", &x[i], &y[i], &z[i]);
        -- x[i]; -- y[i];
    }
    // int n, m; cin >> n >> m;
    // vector<int> a(m), b(m);
    // repeat (e,m) {
    //     cin >> a[e] >> b[e];
    //     -- a[e]; -- b[e];
    // }
    // int q; cin >> q;
    // vector<int> x(q), y(q), z(q);
    // repeat (i,q) {
    //     cin >> x[i] >> y[i] >> z[i];
    //     -- x[i]; -- y[i];
    // }
    // prepare
    vector<persistent_disjoint_sets> t(m+1);
    t[0] = persistent_disjoint_sets(n);
    repeat (i,m) {
        t[i+1] = t[i];
        t[i+1].union_sets(a[i], b[i]);
        // if ((i+1) % (m / 12 + 1) == 0) {
        //     t[i+1] = t[i+1].deepcopy();
        //     repeat (j,n) {
        //         t[i+1].unsafe_find_root(j);
        //     }
        // }
    }
    // output
    repeat (i,q) {
        int low = -1, high = m;
        while (low + 1 < high) {
            int mid = (low + high) / 2;
            (t[mid].query(x[i], y[i]) < z[i] ? low : high) = mid;
        }
        cout << high << endl;
    }
    return 0;
}

Submission Info

Submission Time
Task D - Stamp Rally
User kimiyuki
Language C++14 (GCC 5.4.1)
Score 0
Code Size 4766 Byte
Status TLE
Exec Time 2121 ms
Memory 179328 KB

Compile Error

./Main.cpp: In function ‘int main()’:
./Main.cpp:89:36: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
     int n, m; scanf("%d%d", &n, &m);
                                    ^
./Main.cpp:92:36: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
         scanf("%d%d", &a[e], &b[e]);
                                    ^
./Main.cpp:95:27: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
     int q; scanf("%d", &q);
                           ^
./Main.cpp:98:45: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
         scanf("%d%d%d", &x[i], &y[i], &z[i]);
                                             ^

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 0 / 1000
Status
AC × 1
AC × 8
TLE × 25
Set Name Test Cases
Sample 0_00.txt
All 0_00.txt, 1_00.txt, 1_01.txt, 1_02.txt, 1_03.txt, 1_04.txt, 1_05.txt, 1_06.txt, 1_07.txt, 1_08.txt, 1_09.txt, 1_10.txt, 1_11.txt, 1_12.txt, 1_13.txt, 1_14.txt, 1_15.txt, 1_16.txt, 1_17.txt, 1_18.txt, 1_19.txt, 1_20.txt, 1_21.txt, 1_22.txt, 1_23.txt, 1_24.txt, 1_25.txt, 1_26.txt, 1_27.txt, 1_28.txt, 1_29.txt, 1_30.txt, 1_31.txt
Case Name Status Exec Time Memory
0_00.txt AC 4 ms 256 KB
1_00.txt AC 1605 ms 179328 KB
1_01.txt AC 1968 ms 179328 KB
1_02.txt AC 1900 ms 179328 KB
1_03.txt TLE 2011 ms 179328 KB
1_04.txt AC 1815 ms 179328 KB
1_05.txt TLE 2054 ms 179328 KB
1_06.txt AC 1950 ms 179328 KB
1_07.txt TLE 2117 ms 179328 KB
1_08.txt TLE 2049 ms 179328 KB
1_09.txt TLE 2117 ms 179328 KB
1_10.txt TLE 2040 ms 179328 KB
1_11.txt TLE 2117 ms 179328 KB
1_12.txt TLE 2041 ms 179328 KB
1_13.txt TLE 2117 ms 179328 KB
1_14.txt AC 1850 ms 179328 KB
1_15.txt AC 1921 ms 179328 KB
1_16.txt TLE 2117 ms 174720 KB
1_17.txt TLE 2121 ms 174720 KB
1_18.txt TLE 2117 ms 173056 KB
1_19.txt TLE 2117 ms 179200 KB
1_20.txt TLE 2116 ms 163968 KB
1_21.txt TLE 2117 ms 177536 KB
1_22.txt TLE 2117 ms 172032 KB
1_23.txt TLE 2117 ms 171648 KB
1_24.txt TLE 2116 ms 162432 KB
1_25.txt TLE 2117 ms 173824 KB
1_26.txt TLE 2120 ms 167040 KB
1_27.txt TLE 2121 ms 174336 KB
1_28.txt TLE 2117 ms 173440 KB
1_29.txt TLE 2116 ms 162560 KB
1_30.txt TLE 2117 ms 172672 KB
1_31.txt TLE 2116 ms 163968 KB