Submission #291240

#TimeUsernameProblemLanguageResultExecution timeMemory
291240penguinhackerKlasika (COCI20_klasika)C++17
33 / 110
5063 ms133160 KiB
#include <bits/stdc++.h> using namespace std; #define ll long long #define ar array const int MAXDIG=30; struct Node { int cnt=0; int nxt[2]; Node() {nxt[0]=nxt[1]=-1;} }; struct Trie { vector<Node> trie; Trie() {trie.emplace_back();} void reset() {trie.clear(); trie.emplace_back();} void add(int x) { int cur=0; ++trie[0].cnt; for (int i=MAXDIG; ~i; --i) { int c=(x>>i)&1; if (trie[cur].nxt[c]==-1) { trie[cur].nxt[c]=trie.size(); trie.emplace_back(); } cur=trie[cur].nxt[c]; ++trie[cur].cnt; } } /*void remove(int x) { int cur=0; --trie[0].cnt; for (int i=MAXDIG; ~i; --i) { int c=(x>>i)&1; assert(trie[cur].nxt[c]!=-1); cur=trie[cur].nxt[c]; --trie[cur].cnt; } }*/ int qry(int x) { //best xor in trie int cur=0; int res=0; for (int i=MAXDIG; ~i; --i) { int c=(x>>i)&1; if (trie[cur].nxt[c^1]!=-1&&trie[trie[cur].nxt[c^1]].cnt>0) { res+=(1<<i); cur=trie[cur].nxt[c^1]; } else { cur=trie[cur].nxt[c]; } } return res; } }; //try to rebuild every sqrt(n) queries, change block size to pass constraints const int mxN=2e5; int totNodes=1, n, val[mxN], parent[mxN]; int pos[mxN], iPos[mxN], sz[mxN], tin[mxN], tout[mxN]; bool vis[mxN]; vector<int> adj[mxN]; Trie tree[4*mxN]; void dfs(int u, int& ind, int& timer) { pos[u]=ind++; iPos[pos[u]]=u; tin[u]=timer++; sz[u]=1; for (int v : adj[u]) { dfs(v, ind, timer); sz[u]+=sz[v]; } tout[u]=timer++; } void buildTree(int u=1, int l=0, int r=n-1) { //takes n*log(n)*31 time around tree[u].reset(); for (int i=l; i<=r; ++i) { tree[u].add(val[iPos[i]]); } if (l==r) return; int mid=(l+r)/2; buildTree(2*u, l, mid), buildTree(2*u+1, mid+1, r); } int qry(int ql, int qr, int x, int u=1, int l=0, int r=n-1) { //take log(n)*31 time around if (l>qr||r<ql) return 0; if (ql<=l&&r<=qr) return tree[u].qry(x); int mid=(l+r)/2; return max(qry(ql, qr, x, 2*u, l, mid), qry(ql, qr, x, 2*u+1, mid+1, r)); } vector<int> toCheck; void rebuild() { n=totNodes; int ind=0, timer=0; dfs(0, ind, timer); buildTree(); for (int i: toCheck) vis[i]=1; toCheck.clear(); } int brute(int u, int x) { int res=x^val[u]; for (int v: adj[u]) res=max(res, brute(v, x)); return res; } int temp[mxN]; int dfs_check(int b, int x) { if (vis[x]) { return tin[b]<=tin[x]&&tout[b]>=tout[x]; } return temp[x]=dfs_check(b, parent[x]); } int main() { ios::sync_with_stdio(0); cin.tie(0); fill(temp, temp+mxN, -1); int q; cin >> q; while(q--) { string type; cin >> type; int a, b; cin >> a >> b; if (type=="Add") { --a; val[totNodes]=val[a]^b; adj[a].push_back(totNodes); parent[totNodes]=a; toCheck.push_back(totNodes); ++totNodes; //rebuild(); if (totNodes%2000==0) rebuild(); } if (type=="Query") { --a, --b; int ans=0; if (vis[b]) { int l=pos[b], r=pos[b]+sz[b]-1; ans=qry(l, r, val[a]); for (int i: toCheck) { if (temp[i]==-1) dfs_check(b, i); if (temp[i]) { ans=max(ans, val[i]^val[a]); } } for (int i: toCheck) temp[i]=-1; } else { ans=brute(b, val[a]); } cout << ans << "\n"; //cout << "testing\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...