Submission #1306565

#TimeUsernameProblemLanguageResultExecution timeMemory
1306565dzhoz0Klasika (COCI20_klasika)C++20
33 / 110
855 ms562012 KiB
/*
    it could have been better :)
    it will next time ;)
*/
#include <bits/stdc++.h>
using namespace std;

#define INF 2e9
#define f first
#define s second
#define pii pair<int, int>
#define vi vector<int>

const int MOD = 1'000'000'000 + 7;

void setIO(string name = "")
{
    ios_base::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
#ifdef LOCAL
    freopen("inp.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#else
    if (!name.empty())
    {
        freopen((name + ".INP").c_str(), "r", stdin);
        freopen((name + ".OUT").c_str(), "w", stdout);
    }
#endif
}

struct SegmentTree {
    int n;
    vector<int> a;
    vector<int> st;

    SegmentTree(int _n) {
        n = _n;
        a.assign(n + 1, 0);
        st.assign(4 * n + 5, INF);
    }

    void build(int id, int l, int r) {
        if (l == r) {
            st[id] = a[l];
            return;
        }
        int mid = (l + r) >> 1;
        build(id * 2, l, mid);
        build(id * 2 + 1, mid + 1, r);
        st[id] = min(st[id * 2], st[id * 2 + 1]);
    }

    void update(int id, int l, int r, int i, int val) {
        if (i < l || i > r) return;
        if (l == r) {
            st[id] = val;
            return;
        }
        int mid = (l + r) >> 1;
        update(id * 2, l, mid, i, val);
        update(id * 2 + 1, mid + 1, r, i, val);
        st[id] = min(st[id * 2], st[id * 2 + 1]);
    }

    int get(int id, int l, int r, int u, int v) {
        if (v < l || u > r) return INF;
        if (u <= l && r <= v) return st[id];
        int mid = (l + r) >> 1;
        int left = get(id * 2, l, mid, u, v);
        int right = get(id * 2 + 1, mid + 1, r, u, v);
        return min(left, right);
    }
};

struct Trie {
    struct Node {
        int cnt = 0;
        vector<pii> v;
        vi v_nw; 
        SegmentTree *seg = nullptr;
        int n; 
        int child[2] = {-1, -1};

        void init() {
            sort(v.begin(), v.end()); 
            n = (int)v.size();
            seg = new SegmentTree(n);
            for (int i = 0; i < n; ++i) {
                seg->a[i + 1] = v[i].s; 
                v_nw.push_back(v[i].f); 
            }
            seg->build(1, 1, n);
        }

        int query_min(int l, int r) {
            if (n == 0) return INF;
            return seg->get(1, 1, n, l + 1, r + 1);
        }

        bool exist(int time_in, int time_out, int time_query) {
            if (v_nw.empty()) return false;
            auto it1 = lower_bound(v_nw.begin(), v_nw.end(), time_in);
            auto it2 = upper_bound(v_nw.begin(), v_nw.end(), time_out);
            if (it1 == v_nw.end()) return false;
            int id1 = it1 - v_nw.begin(), id2 = it2 - v_nw.begin();
            if (id1 >= id2) return false;
            return query_min(id1, id2 - 1) <= time_query;
        }
    };

    vector<Node> trie = {Node()};

    void add(int x, pii it) {
        int node = 0;
        trie[node].v.push_back(it);
        for (int b = 30; b >= 0; b--) {
            int cur = (x >> b) & 1;
            if (trie[node].child[cur] == -1) {
                trie[node].child[cur] = trie.size();
                trie.emplace_back();
            }
            node = trie[node].child[cur];
            trie[node].v.push_back(it);
        }
        trie[node].cnt++;
    }

    int query(int x, int time_in, int time_out, int time_query) {
        int node = 0;
        int cur_value = 0;
        for (int b = 30; b >= 0; b--) {
            int cur = 1 - ((x >> b) & 1);
            if (trie[node].child[cur] != -1 && trie[trie[node].child[cur]].exist(time_in, time_out, time_query))
                node = trie[node].child[cur];
            else if (trie[node].child[1 - cur] != -1 && trie[trie[node].child[1 - cur]].exist(time_in, time_out, time_query)) {
                node = trie[node].child[1 - cur];
                cur = 1 - cur;
            } else return x;
            if (cur == 1) cur_value |= (1 << b);
        }
        if (trie[node].cnt > 0) return cur_value;
        return x;
    }

    void init() {
        for (auto &it : trie) it.init();
    }
} trie;

struct Query {
    int type;
    int x, y, w;
};

const int MAXN = 2e5;

int d[MAXN + 5];
vi g[MAXN + 5];
int tin[MAXN + 5], tout[MAXN + 5];
int timeAdd[MAXN + 5];
int timeDfs = 0;
void dfs(int u) {
    tin[u] = ++timeDfs;
    for(int &v : g[u]) dfs(v);
    tout[u] = timeDfs;
}

void solve()
{
    int q; cin >> q;
    vector<Query> queries(q);
    int n = 1;
    d[1] = 0;
    timeAdd[1] = -1;
    {
        int cur = 1; 
        for(int i = 0; i < q; i++) {
            auto &it = queries[i];
            string s; cin >> s;
            if(s == "Add") it.type = 0;
            else it.type = 1;
            cin >> it.x;
            if(it.type == 0) {
                cin >> it.w;
                it.y = ++cur;
                n++;
                timeAdd[it.y] = i;
                g[it.x].push_back(it.y);
                d[it.y] = d[it.x] ^ it.w;
            }
            else {
                cin >> it.y;
            }
            // cout << it.x << ' ' << it.y << ' ' << it.w << '\n';

        }
    }

    dfs(1);
    for(int i = 1; i <= n; i++) trie.add(d[i], {tin[i], timeAdd[i]}); 
    trie.init(); 

    for(int i = 0; i < q; i++) {
        auto it = queries[i];
        if(it.type == 0) continue;
        cout << (d[it.x] ^ trie.query(d[it.x], tin[it.y], tout[it.y], i)) << '\n';
    }

}
signed main()
{
    setIO();
    int t = 1;
    // cin >> t;
    while (t--)
        solve();
}

Compilation message (stderr)

klasika.cpp: In function 'void setIO(std::string)':
klasika.cpp:26:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   26 |         freopen((name + ".INP").c_str(), "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
klasika.cpp:27:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   27 |         freopen((name + ".OUT").c_str(), "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...