1778E - The Tree Has Fallen - CodeForces Solution


bitmasks dfs and similar math trees

Please click on ads to support us..

C++ Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<vi> vvi;
typedef vector<vll> vvll;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<pdd> vpdd;
typedef vector<vd> vvd;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
template<class T> bool chmax(T &a, T b) {
	if (a >= b) return false;
	a = b; return true;
}
template<class T> bool chmin(T &a, T b) {
	if (a <= b) return false;
	a = b; return true;
}
#define FOR(i, s, e, t) for ((i) = (s); (i) < (e); (i) += (t)) 
#define REP(i, e) for (int i = 0; i < (e); ++i) 
#define REP1(i, s, e) for (int i = (s); i < (e); ++i)
#define RREP(i, e) for (int i = (e); i >= 0; --i)
#define RREP1(i, e, s) for (int i = (e); i >= (s); --i)
#define all(v) v.begin(), v.end()
#define pb push_back
#define qb pop_back
#define pf push_front
#define qf pop_front
#define maxe max_element
#define mine min_element
ll inf = 1e18;
#define DEBUG printf("%d\n", __LINE__); fflush(stdout);
template<class T> void print(vector<T> &v, bool withSize = false) {
	if (withSize) cout << v.size() << endl;
	REP(i, v.size()) cout << v[i] << " "; 
	cout << "\n";
}
mt19937_64 rng((unsigned int) chrono::steady_clock::now().time_since_epoch().count());

int __FAST_IO__ = []() {
	std::ios::sync_with_stdio(0);
	std::cin.tie(0);
	std::cout.tie(0);
	return 0;
}();

vector<vector<int>> readGraph(int N, int M, bool isDirected = false) {
	vector<vector<int>> g(N);
    REP(i, M) {
    	int u, v;
	    cin >> u >> v;
    	--u, --v;
    	g[u].push_back(v);
    	if (!isDirected) g[v].push_back(u);
    }
    return g;
}

class LCA {
public:
    LCA(vector<vector<int>> &_g): N(_g.size()), depth(N, 0), sz(N, 1), g(_g), dp(N, vi(20, -1)) {
        dfs(0, -1);
    }
    
    void dfs(int cur, int par) {
        if (par != -1) {
    	    depth[cur] = depth[par] + 1;
    	    dp[cur][0] = par;
    	    int x = par;
    	    REP1(i, 1, 20) {
    	        dp[cur][i] = dp[x][i - 1];
    	        x = dp[x][i - 1];
    	        if (x == -1) break;
    	    }
    	}
    	for (auto son: g[cur]) {
    	    if (son == par) continue;
    	    dfs(son, cur);
	    sz[cur] += sz[son];
    	}
    }
    
    int lca(int u, int v) {
        if (depth[u] < depth[v]) swap(u, v);
    	int diff = depth[u] - depth[v];
        REP(i, 20) {
            if (diff >> i & 1) u = dp[u][i];
        }
        while (u != v) {
            if (dp[u][0] == dp[v][0]) return dp[u][0];
            REP1(i, 1, 20) {
                if (dp[u][i] == dp[v][i]) {
                    u = dp[u][i - 1];
                    v = dp[v][i - 1];
                    break;
                }
            }
        }
        return u;
    }
    
    int dis(int u, int v) {
    	int par = lca(u, v);
    	return depth[u] + depth[v] - 2 * depth[par];
    }

    int dep(int u) {return depth[u];}
    int size(int u) {return sz[u];}

    int parent(int u, int d) {
        REP(i, 20) {
            if (d >> i & 1) u = dp[u][i];
        }
        return u;
    }

    bool isParent(int u, int v) {
        if (dep(u) > dep(v)) return false;
        int d = dis(u, v);
        return dep(v) >= d && parent(v, d) == u;
    }

    bool inPath(int s, int t, int k) {
    	int p = lca(s, t);
    	return (isParent(p, k) && (isParent(k, s) || isParent(k, t)));
    }


    int N;
    vi depth, sz;
    vvi g, dp; 
};

int main() {
    int t;
    cin >> t;
    while (t--) {
    	int N, Q;
    	cin >> N;
    	vi v(N);
    	REP(i, N) cin >> v[i];
    	
    	auto g = readGraph(N, N - 1);
    	LCA lca(g);
    	
    	vvi base(N, vi(30, 0)), base2(N, vi(30, 0));
    	vector<vvi> left(N), right(N);
    	vi id(N);
    	auto merge = [&](vi &b, int e) {
    		RREP(i, 29) {
    			if (!(e >> i & 1)) continue;
    			if (!b[i]) {
    				b[i] = e;
    				return;
    			}
    			e ^= b[i];
    		}
    	};
    	
    	auto merge2 = [&](vi &from, vi &to) {
    		RREP(i, 29) if (to[i] != 0) merge(from, to[i]);	
    	};
    	
    	function<void(int, int)> dfs = [&](int cur, int par) {
    		merge(base[cur], v[cur]);
    		if (par != -1) g[cur].erase(find(all(g[cur]), par));
    		for (auto next: g[cur]) {
    			dfs(next, cur);
    			merge2(base[cur], base[next]);
    		}
    		
    	};
    	dfs(0, -1);

    	vi p(30, 0);
    	function<void(int, int, vi &)> dfs2 = [&](int cur, int par, vi &p) {
    		base2[cur] = p;
    		left[cur].resize(g[cur].size() + 1, vi(30, 0));
    		right[cur].resize(g[cur].size() + 1, vi(30, 0));
    		REP(i, g[cur].size()) {
    			id[g[cur][i]] = i;
    			left[cur][i + 1] = left[cur][i];
    			merge2(left[cur][i + 1], base[g[cur][i]]);
    			int j = g[cur].size() - 1 - i;
    			right[cur][j] = right[cur][j + 1];
    			merge2(right[cur][j], base[g[cur][j]]);
    		}
			
    		REP(i, g[cur].size()) {
    			int next = g[cur][i];
    			auto q = p;
    			merge(q, v[cur]);
    			merge2(q, left[cur][i]);
    			merge2(q, right[cur][i + 1]);
    			dfs2(next, cur, q);
    		}
    	};
    	dfs2(0, -1, p);

		cin >> Q;
    	REP(i, Q) {
    		int R, U;
    		cin >> R >> U;
    		--R, --U;
    		vi p;
    		if (R == U) {
    			p = base[0];
    		} else if (lca.lca(R, U) == U) {
    			int V = lca.parent(R, lca.dep(R) - lca.dep(U) - 1);
    			p = base2[U];
    			merge(p, v[U]);
    			int j = id[V];
    			merge2(p, left[U][j]);
    			merge2(p, right[U][j + 1]);
    		} else {
    			p = base[U];
    		}
    		
    		int ans = 0;
			RREP(i, 29) {
				if (p[i] != 0 && !(ans >> i & 1)) ans ^= p[i];
			}
			printf("%d\n", ans);
    	}
    }
    
    return 0;
}


Comments

Submit
0 Comments
More Questions

1437A - Marketing Scheme
1473B - String LCM
1374A - Required Remainder
1265E - Beautiful Mirrors
1296A - Array with Odd Sum
1385A - Three Pairwise Maximums
911A - Nearest Minimums
102B - Sum of Digits
707A - Brain's Photos
1331B - Limericks
305B - Continued Fractions
1165B - Polycarp Training
1646C - Factorials and Powers of Two
596A - Wilbur and Swimming Pool
1462B - Last Year's Substring
1608B - Build the Permutation
1505A - Is it rated - 2
169A - Chores
765A - Neverending competitions
1303A - Erasing Zeroes
1005B - Delete from the Left
94A - Restoring Password
1529B - Sifid and Strange Subsequences
1455C - Ping-pong
1644C - Increase Subarray Sums
1433A - Boring Apartments
1428B - Belted Rooms
519B - A and B and Compilation Errors
1152B - Neko Performs Cat Furrier Transform
1411A - In-game Chat