제출 #1181648

#제출 시각아이디문제언어결과실행 시간메모리
1181648sqrtxsunlightFloppy (RMI20_floppy)C++17
컴파일 에러
0 ms0 KiB
#include "floppy.h" // Include the header provided by the problem statement
#include <vector>
#include <string>
#include <stack>
#include <algorithm>
#include <memory> // Required for unique_ptr if used, though direct arrays/vectors are fine too

// --- Global data for Interaction 1 (will be lost before Interaction 2) ---
// Not strictly necessary to be global, can be local to read_array
namespace interaction1 {
    std::vector<int> left_child;
    std::vector<int> right_child;
    std::vector<int> parent;
    std::string encoded_bits;

    // Recursive function to encode the tree structure (preorder)
    void encode_tree(int u) {
        if (u == -1) {
            encoded_bits += '0';
            return;
        }
        encoded_bits += '1';
        encode_tree(left_child[u]);
        encode_tree(right_child[u]);
    }
} // namespace interaction1

// --- Global data for Interaction 2 ---
namespace interaction2 {
    int N;
    std::vector<int> left_child;
    std::vector<int> right_child;
    std::vector<int> parent; // Parent needed for LCA precomputation
    std::vector<int> node_to_original_index;
    std::vector<int> original_index_to_node;
    std::string::const_iterator bit_iterator; // To iterate through the bits string

    // LCA related data (using binary lifting)
    const int MAX_LOG_N = 18; // ceil(log2(40000)) + a bit extra
    std::vector<std::vector<int>> up; // up[k][u] = 2^k-th ancestor of u
    std::vector<int> depth;

    int current_node_id = 0;
    int current_original_index = 0;

    // Recursive function to decode the bit string and build the tree structure
    int decode_tree(const std::string& bits) {
        if (bit_iterator == bits.end() || *bit_iterator == '0') {
            ++bit_iterator; // Consume the '0'
            return -1; // Represents a null child
        }

        ++bit_iterator; // Consume the '1'
        int node_id = current_node_id++;
        left_child[node_id] = decode_tree(bits);
        right_child[node_id] = decode_tree(bits);

        // Set parent pointers during reconstruction
        if (left_child[node_id] != -1) {
            parent[left_child[node_id]] = node_id;
        }
        if (right_child[node_id] != -1) {
            parent[right_child[node_id]] = node_id;
        }
        return node_id;
    }

    // Inorder traversal to assign original indices
    void assign_indices_inorder(int u) {
        if (u == -1) {
            return;
        }
        assign_indices_inorder(left_child[u]);
        // Assign original index during the inorder visit
        node_to_original_index[u] = current_original_index;
        original_index_to_node[current_original_index] = u;
        current_original_index++;
        assign_indices_inorder(right_child[u]);
    }

    // Depth First Search to compute depths and immediate parents for LCA
    void dfs_lca(int u, int p, int d) {
        depth[u] = d;
        up[0][u] = p; // Immediate parent (or -1 for root)
        if (left_child[u] != -1) {
            dfs_lca(left_child[u], u, d + 1);
        }
        if (right_child[u] != -1) {
            dfs_lca(right_child[u], u, d + 1);
        }
    }

    // Precompute LCA using binary lifting
    void build_lca(int root) {
        depth.assign(N, 0);
        up.assign(MAX_LOG_N, std::vector<int>(N, -1));

        dfs_lca(root, -1, 0); // Compute depth and up[0]

        for (int k = 1; k < MAX_LOG_N; ++k) {
            for (int u = 0; u < N; ++u) {
                if (up[k - 1][u] != -1) {
                    up[k][u] = up[k - 1][up[k - 1][u]];
                }
            }
        }
    }

    // Query LCA
    int get_lca(int u, int v) {
        if (depth[u] < depth[v]) {
            std::swap(u, v);
        }

        // Bring u to the same depth as v
        for (int k = MAX_LOG_N - 1; k >= 0; --k) {
            if (up[k][u] != -1 && depth[up[k][u]] >= depth[v]) {
                u = up[k][u];
            }
        }

        if (u == v) {
            return u;
        }

        // Lift u and v together
        for (int k = MAX_LOG_N - 1; k >= 0; --k) {
            if (up[k][u] != up[k][v]) {
                u = up[k][u];
                v = up[k][v];
            }
        }
        // Now up[0][u] == up[0][v] is the LCA
        return up[0][u];
    }

} // namespace interaction2

// --- Interaction 1 Implementation ---
void read_array(int subtask_id, const std::vector<int>& v) {
    int n = v.size();
    interaction1::left_child.assign(n, -1);
    interaction1::right_child.assign(n, -1);
    interaction1::parent.assign(n, -1);
    interaction1::encoded_bits = "";

    // Build Cartesian Tree using O(N) stack method
    std::stack<int> s;
    for (int i = 0; i < n; ++i) {
        int last_popped = -1;
        while (!s.empty() && v[s.top()] < v[i]) {
            last_popped = s.top();
            s.pop();
        }
        interaction1::left_child[i] = last_popped;
        if (last_popped != -1) {
            interaction1::parent[last_popped] = i;
        }
        if (!s.empty()) {
            interaction1::right_child[s.top()] = i;
            interaction1::parent[i] = s.top();
        }
        s.push(i);
    }

    // Find the root (the node with no parent)
    int root = -1;
    for (int i = 0; i < n; ++i) {
        if (interaction1::parent[i] == -1) {
            root = i;
            break;
        }
    }

    // Encode the tree structure
    interaction1::encode_tree(root);

    // Save the bits
    save_to_floppy(interaction1::encoded_bits);
    assert (interaction1::encoded_bits.size () <= v.size () * 2);
}

// --- Interaction 2 Implementation ---
std::vector<int> solve_queries(int subtask_id, int N_in, const std::string& bits, const std::vector<int>& a, const std::vector<int>& b) {
    interaction2::N = N_in;
    interaction2::left_child.assign(N_in, -1);
    interaction2::right_child.assign(N_in, -1);
    interaction2::parent.assign(N_in, -1); // Important for LCA precomputation
    interaction2::node_to_original_index.assign(N_in, -1);
    interaction2::original_index_to_node.assign(N_in, -1);
    interaction2::bit_iterator = bits.begin();
    interaction2::current_node_id = 0; // Reset counters for reconstruction
    interaction2::current_original_index = 0;


    // 1. Reconstruct the tree structure from bits
    int root = interaction2::decode_tree(bits);
    // The parent array is partially filled by decode_tree, root's parent remains -1.

    // 2. Assign original indices using inorder traversal
    interaction2::assign_indices_inorder(root);

    // 3. Precompute LCA data structures
    interaction2::build_lca(root);

    // 4. Answer queries
    int M = a.size();
    std::vector<int> results(M);
    for (int i = 0; i < M; ++i) {
        int u_orig_idx = a[i];
        int v_orig_idx = b[i];

        // Handle query for single element range
        if (u_orig_idx == v_orig_idx) {
             results[i] = u_orig_idx;
             continue;
        }

        int u_node = interaction2::original_index_to_node[u_orig_idx];
        int v_node = interaction2::original_index_to_node[v_orig_idx];

        int lca_node = interaction2::get_lca(u_node, v_node);
        results[i] = interaction2::node_to_original_index[lca_node];
    }

    return results;
}

컴파일 시 표준 에러 (stderr) 메시지

floppy.cpp: In function 'void read_array(int, const std::vector<int>&)':
floppy.cpp:180:5: error: 'assert' was not declared in this scope
  180 |     assert (interaction1::encoded_bits.size () <= v.size () * 2);
      |     ^~~~~~
floppy.cpp:7:1: note: 'assert' is defined in header '<cassert>'; did you forget to '#include <cassert>'?
    6 | #include <memory> // Required for unique_ptr if used, though direct arrays/vectors are fine too
  +++ |+#include <cassert>
    7 |