Submission #1314549

#TimeUsernameProblemLanguageResultExecution timeMemory
1314549duongnguyen0210Klasika (COCI20_klasika)C++20
33 / 110
796 ms589824 KiB
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 200005;
const int LOG_VAL = 30;

struct QueryInfo {
    int id;         // ID của truy vấn (để in ra đúng thứ tự)
    int type;       // 0: Add, 1: Query
    int u;          // Add: node index, Query: start node a
    int v;          // Add: weight, Query: subtree node b
    int time_added; // Add: thời điểm thêm (node ID)
};

int n = 1, q;
vector<pair<int, int>> adj[MAXN];
int st[MAXN], en[MAXN], D[MAXN]; // D[u] là XOR path từ root đến u
int timer;
int ans[MAXN]; // Lưu kết quả truy vấn
vector<QueryInfo> queries;

// DFS để linearize cây (Euler tour) và tính XOR path
void dfs(int u, int p) {
    st[u] = ++timer;
    for (auto &edge : adj[u]) {
        int v = edge.first;
        int w = edge.second;
        if (v != p) {
            D[v] = D[u] ^ w;
            dfs(v, u);
        }
    }
    en[u] = timer;
}

struct Node {
    Node *child[2];
    int cnt;
    Node() { child[0] = child[1] = NULL; cnt = 0; }
};

Node* null;

void init_trie() {
    null = new Node();
    null->child[0] = null->child[1] = null;
    null->cnt = 0;
}

void insert(Node* prev, Node* &curr, int val) 
{
    curr = new Node();
    *curr = *prev;
    curr->cnt++;
    
    Node* p = curr;
    for (int i = LOG_VAL; i >= 0; i--) 
    {
        int bit = (val >> i) & 1;
        p->child[bit] = new Node();
        *p->child[bit] = *prev->child[bit]; 
        p->child[bit]->cnt++;
        p = p->child[bit];
        prev = prev->child[bit];
    }
}

int query(Node* verL, Node* verR, int val) 
{
    int res = 0;
    for (int i = LOG_VAL; i >= 0; i--) 
    {
        int bit = (val >> i) & 1;
        int want = 1 - bit;
        if (verR->child[want]->cnt - verL->child[want]->cnt > 0) 
        {
            res += (1 << i);
            verR = verR->child[want];
            verL = verL->child[want];
        } 
        else 
        {
            verR = verR->child[bit];
            verL = verL->child[bit];
        }
    }
    return res;
}

Node* roots[MAXN]; 

void solve_cdq(int l, int r, vector<int>& q_indices) 
{
    if (q_indices.empty()) 
        return;
    if (l == r) 
        return;

    int mid = (l + r) >> 1;
    vector<int> left_q, right_q;

    for (int id : q_indices) 
    {
        if (queries[id].id <= mid) 
            left_q.push_back(id);
        else 
            right_q.push_back(id);
    }

    solve_cdq(l, mid, left_q);
    solve_cdq(mid + 1, r, right_q);

    vector<pair<int, int>> nodes_to_add;
    for (int id : left_q) {
        if (queries[id].type == 0) 
        { 
            int u = queries[id].time_added;
            nodes_to_add.push_back({st[u], D[u]});
        }
    }
    
    if (l == 1) 
        nodes_to_add.push_back({st[1], D[1]});


    sort(nodes_to_add.begin(), nodes_to_add.end());

    vector<Node*> versions;
    vector<int> version_st;
    
    Node* current_root = null;
    versions.push_back(null); 
    version_st.push_back(0);

    for (auto p : nodes_to_add) 
    {
        int pos = p.first;
        int val = p.second;
        Node* new_root;
        insert(current_root, new_root, val);
        current_root = new_root;
        versions.push_back(current_root);
        version_st.push_back(pos);
    }

    for (int id : right_q) 
    {
        if (queries[id].type == 1) 
        { 
            int u = queries[id].u; 
            int b = queries[id].v;
            auto itR = upper_bound(version_st.begin(), version_st.end(), en[b]);
            int idxR = prev(itR) - version_st.begin();
            auto itL = upper_bound(version_st.begin(), version_st.end(), st[b] - 1);
            int idxL = prev(itL) - version_st.begin();
            
            int val = query(versions[idxL], versions[idxR], D[u]);
            ans[id] = max(ans[id], val);
        }
    }
}

int main() 
{
    ios_base::sync_with_stdio(false); 
    cin.tie(NULL);
    init_trie();
    cin >> q;
    int node_cnt = 1;
    queries.resize(q + 1); 
    
    for (int i = 1; i <= q; i++) 
    {
        string type;
        int u, v;
        cin >> type >> u >> v;
        queries[i].id = i;
        if (type == "Add") 
        {
            queries[i].type = 0;
            queries[i].u = u; 
            queries[i].v = v; 
            node_cnt++;
            queries[i].time_added = node_cnt; 
            adj[u].push_back({node_cnt, v});
            adj[node_cnt].push_back({u, v});
        } 
        else 
        {
            queries[i].type = 1;
            queries[i].u = u; 
            queries[i].v = v; 
            ans[i] = 0;
        }
    }
    D[1] = 0;
    dfs(1, 0);

    vector<int> q_indices;
    for(int i = 1; i <= q; i++) 
        q_indices.push_back(i);

    solve_cdq(1, q, q_indices);

    for (int i = 1; i <= q; i++) 
        if (queries[i].type == 1) 
            cout << ans[i] << "\n";

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...