제출 #1352284

#제출 시각아이디문제언어결과실행 시간메모리
1352284chithanhnguyenKlasika (COCI20_klasika)C++20
110 / 110
294 ms170032 KiB
#include <bits/stdc++.h>
using namespace std;

// #define int long long
#define ull unsigned long long
#define ld long double
#define pii pair<int, int>
#define fi first
#define se second
#define __builtin_popcount __builtin_popcountll
#define all(x) (x).begin(), (x).end()
#define BIT(x, i) (((x) >> (i)) & 1)
#define MASK(x) ((1ll << (x)))

#define debug(a, l, r) for (int _i = (l); _i <= (r); ++_i) cout << (a)[_i] << ' '; cout << '\n';

const int MAXCHAR = 2;
const int LG = 30;
const int INF = 1e9 + 5;
// 

void minimize(int &x, int y) {
    if (x > y) x = y;
}

struct Node{
    Node* child[MAXCHAR];
    int time = INF;

    Node() {
        fill(child, child+MAXCHAR, nullptr);
    }
};

vector<Node*> stk;
vector<pair<Node*, Node*>> st;

struct BinaryTrie{
    Node root;
    int numNode = 1;
    // vector<pii> nums;

    BinaryTrie() {
        root = Node();
    }

    void reset() {
        clearNode(&root);
        root = Node();
        numNode = 1;
        // nums.clear();
    }

    void clearNode(Node* root) {
        // stack<Node*> st;
        stk.push_back(root);
        while (!stk.empty()) {
            Node* cur = stk.back();
            stk.pop_back();
            for (int i = 0; i < MAXCHAR; ++i) {
                if (cur->child[i]) {
                    stk.push_back(cur->child[i]);
                    cur->child[i] = nullptr;
                }
            }
            if (cur != root) delete cur;
            // else cur->time = INF;
        }
    }

    void addNum(int x, int t) {
        // nums.push_back({x, t});
        Node *cur = &root;
        minimize(cur->time, t);
        for (int i = LG; i >= 0; --i){
            int c = BIT(x, i);
            if (!(cur->child[c])) {
                cur->child[c] = new Node();
                ++numNode;
            }
            cur = cur->child[c];
            minimize(cur->time, t);
        }
    }

    int findMaximumXor(int x, int t) {
        Node *cur = &root;
        int res = 0;

        for (int i = LG; i >= 0; --i) {
            int need = BIT(x, i) ^ 1;
            if (!(cur->child[need])) need ^= 1;
            else {
                if (cur->child[need]->time > t) need ^= 1;
            }
            res += MASK(i) * (need ^ BIT(x, i));
            cur = cur->child[need];
        }

        return res;
    }
};

void mergeTrie(Node* big, Node* small) {
    if (!small) return;

    st.push_back({big, small});
    
    while (!st.empty()) {
        pair<Node*, Node*> cur = st.back();
        st.pop_back();
        Node* b = cur.fi;
        Node* s = cur.se;

        minimize(b->time, s->time);

        for (int i = 0; i < MAXCHAR; ++i) {
            if (!s->child[i]) continue;

            if (!b->child[i]) {
                b->child[i] = s->child[i];
            } else {
                st.push_back({b->child[i], s->child[i]});
            }

            s->child[i] = nullptr;
        }
    }
}



struct Query{
    int a, time;
};

const int MAXN = 2e5 + 5;
vector<pii> adj[MAXN];
int q, n, appear[MAXN], f[MAXN];
// int st[MAXN], en[MAXN], timer = 0;
vector<Query> queries[MAXN];
BinaryTrie trie[MAXN];
int ans[MAXN];

void dfs(int u, int par = 0) {
    // st[u] = ++timer;

    for (auto &e : adj[u]) {
        int v = e.fi, w = e.se;

        if (v == par) continue;

        f[v] = f[u] ^ w;
        dfs(v, u);
    }

    // en[u] = timer;
}

void init() {
    cin >> q; n = 1;
    memset(ans, -1, sizeof ans);
    for (int i = 1; i <= q; ++i) {
        string type; cin >> type;
        int a, b; cin >> a >> b;
        if (type == "Add") {
            adj[a].push_back({n + 1, b});
            adj[n + 1].push_back({a, b});
            ++n;
            appear[n] = i;
        } 
        else {
            queries[b].push_back({a, i});
        }
    }

    dfs(1);
    // for (int i = 1; i <= n; ++i) {
    //     // cout << st[i] << ' ' << en[i] << '\n';
    //     // cout << appear[i] << '\n';
    //     // cout << f[i] << '\n';
    //     // cout << "dfsdf:\n";
    //     addNum(f[i], st[i], en[i], appear[i]);
    // }
}

void dfs_solve(int u, int par = -1) {
    for (auto &e : adj[u]) {
        int v = e.fi;
        if (v == par) continue;
        dfs_solve(v, u);
        
        if (trie[u].numNode < trie[v].numNode)
            swap(trie[u], trie[v]);
        mergeTrie(&trie[u].root, &trie[v].root);
        trie[v].reset();
    }

    trie[u].addNum(f[u], appear[u]);

    for (auto &qry : queries[u]) {
        int a = qry.a, time = qry.time;
        // cout << i << ' ' << a << ' ' << time << '\n';
        ans[time] = trie[u].findMaximumXor(f[a], time);
    }
}

void solve() {
    // debug(f, 1, n);
    // BinaryTrie trie;
    // for (int i = 1; i <= n; ++i) {
    //     trie.reset();
    //     for (int j = 1; j <= n; ++j) {
    //         if (st[i] <= st[j] && st[j] <= en[i])
    //             trie.addNum(f[j], appear[j]);
    //     }

    //     for (auto &qry : queries[i]) {
    //         int a = qry.a, time = qry.time;
    //         // cout << i << ' ' << a << ' ' << time << '\n';
    //         ans[time] = trie.findMaximumXor(f[a], time);
    //     }
    // }
    // for (int u = 1; u <= n; ++u)
    dfs_solve(1);
    for (int i = 1; i <= q; ++i)
        if (ans[i] != -1) cout << ans[i] << '\n';
}

signed main() {
    #ifdef NCTHANH
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif
    ios_base::sync_with_stdio(0);
    cin.tie(nullptr); cout.tie(nullptr);

    init();
    solve();

    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...