제출 #792670

#제출 시각아이디문제언어결과실행 시간메모리
792670Sohsoh84Werewolf (IOI18_werewolf)C++17
100 / 100
1004 ms243476 KiB
#include "werewolf.h"
#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> pll;

#define all(x)		(x).begin(), (x).end()
#define X		first
#define Y		second
#define sep		' '
#define debug(x)	cerr << #x << ": " << x << endl;

const int MAXN = 1e6 + 10;
const int LOG = 20;

int n, m, q;

namespace DSU_L {
	int C[MAXN], F[MAXN], par[MAXN][LOG], sz, T[MAXN], dfs_time, tin[MAXN], tout[MAXN];
	vector<int> adj[MAXN];

	inline void init() {
		sz = n - 1;
		T[0] = -1;
		for (int i = 0; i < n; i++) {
			F[i] = C[i] = i;
			T[i] = MAXN;
		}
	}

	inline int find(int v) {
		return C[v] == v ? v : C[v] = find(C[v]);
	}

	inline bool unite(int u, int v, int l) {
		u = find(u), v = find(v);
		if (u == v) return false;

		int fu = F[u], fv = F[v];
		sz++;
		par[fu][0] = sz;
		par[fv][0] = sz;
		
		C[v] = u;
		T[sz] = l;
		F[u] = sz;
		
		adj[sz].push_back(fu);
		adj[sz].push_back(fv);

		return true;
	}

	void dfs(int v) {
		tin[v] = ++dfs_time;
		for (int u : adj[v])
			dfs(u);
		
		tout[v] = dfs_time;
	}

	inline void init_tree() {
		dfs(sz);
		par[sz][0] = sz;
		for (int i = 1; i < LOG; i++)
			for (int v = 0; v <= sz; v++)
				par[v][i] = par[par[v][i - 1]][i - 1];
	}

	inline int max_node(int v, int l) {
		for (int i = LOG - 1; i >= 0; i--)
			if (T[par[v][i]] >= l)
				v = par[v][i];

		return v;
	} 

	inline pll get_seg(int v, int l) {
		v = max_node(v, l);
		return {tin[v], tout[v]};
	}
}

namespace DSU_R {
	int par[MAXN];
	vector<int> C[MAXN];
	set<int> st[MAXN];

	inline void init() {
		for (int i = 0; i < n; i++) {
			st[i].insert(DSU_L::tin[i]);
			par[i] = i;
			C[i].push_back(i);
		}
	}

	inline bool unite(int u, int v) {
		u = par[u], v = par[v];
		if (u == v) return false;
		if (C[u].size() < C[v].size()) swap(u, v);

		for (int e : C[v]) {
			C[u].push_back(e);
			par[e] = u;
		}

		for (int e : st[v])
			st[u].insert(e);

		C[v].clear();
		st[v].clear();
		return true;
	}

	inline bool get(int v, int l, int r) {
		v = par[v];
		auto it = st[v].lower_bound(l);
		return it != st[v].end() && *it <= r;
	}
}

vector<int> ans, adj[MAXN], QR[MAXN];

vector<int> check_validity(int N_, vector<int> X_, vector<int> Y_,
	vector<int> S, vector<int> E,
	vector<int> L, vector<int> R) {
	
	n = N_;
	m = X_.size();
	q = S.size();
	
	for (int i = 0; i < m; i++) {
		adj[X_[i]].push_back(Y_[i]);
		adj[Y_[i]].push_back(X_[i]);
	}

	DSU_L::init();

	for (int v = n - 1; v >= 0; v--) {
		for (int u : adj[v]) {
			if (u < v) continue;
			DSU_L::unite(u, v, v);	
		}
	}
	
	DSU_L::init_tree();
	DSU_R::init();
	
	for (int i = 0; i < q; i++)
		QR[R[i]].push_back(i);

	ans.resize(q);
	for (int r = 0; r < n; r++) {
		for (int u : adj[r]) {
			if (u > r) continue;
			DSU_R::unite(r, u);
		}

		for (int i : QR[r]) {
			auto [tl, tr] = DSU_L::get_seg(S[i], L[i]);
			ans[i] = DSU_R::get(E[i], tl, tr);
		}
	}

	return ans;
}

// TODO: fill ans
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...