Submission #592880

#TimeUsernameProblemLanguageResultExecution timeMemory
592880TemmieWerewolf (IOI18_werewolf)C++17
100 / 100
1263 ms120488 KiB
#include "werewolf.h"
#include <bits/stdc++.h>

struct Dsu {
	
	std::vector <int> p;
	std::vector <std::vector <int>> g;
	std::vector <int> tour;
	std::vector <int> l, r;
	
	inline Dsu(int s) {
		p.resize(s);
		std::iota(p.begin(), p.end(), 0);
		g.resize(s);
		l.resize(s);
		r.resize(s);
	}
	
	inline int find(int v) {
		return v == p[v] ? v : (p[v] = find(p[v]));
	}
	
	inline void unite(int u, int v) {
		if ((u = find(u)) != (v = find(v))) {
			g[u].push_back(v);
			p[v] = u;
		}
	}
	
	void make(int node) {
		l[node] = tour.size();
		tour.push_back(node);
		for (int x : g[node]) {
			make(x);
		}
		r[node] = tour.size();
	}
	
};

struct Rag {
	
	int size;
	std::vector <std::vector <int>> v;
	
	Rag(const std::vector <int>& a) {
		size = 1;
		while (size < (int) a.size()) {
			size <<= 1;
		}
		v.resize(size << 1);
		make(a, 0, 0, size = a.size());
	}
	
	void make(const std::vector <int>& a, int now, int l, int r) {
		if (!(r - l - 1)) {
			v[now].push_back(a[l]);
			return;
		}
		int mid = (l + r) >> 1;
		make(a, now * 2 + 1, l, mid);
		make(a, now * 2 + 2, mid, r);
		for (int lp = 0, rp = 0;
		lp < (int) v[now * 2 + 1].size() || rp < (int) v[now * 2 + 2].size(); ) {
			if (lp == (int) v[now * 2 + 1].size()) v[now].push_back(v[now * 2 + 2][rp++]);
			else if (rp == (int) v[now * 2 + 2].size()) v[now].push_back(v[now * 2 + 1][lp++]);
			else if (v[now * 2 + 1][lp] < v[now * 2 + 2][rp]) v[now].push_back(v[now * 2 + 1][lp++]);
			else v[now].push_back(v[now * 2 + 2][rp++]);
		}
	}
	
	int query(int tl, int tr, int le, int ri) {
		return query(tl, tr, le, ri, 0, 0, size);
	}
	
	int query(int tl, int tr, int le, int ri, int now, int l, int r) {
		if (l >= tr || r <= tl) {
			return 0;
		}
		if (l >= tl && r <= tr) {
			return
			std::lower_bound(v[now].begin(), v[now].end(), ri) -
			std::lower_bound(v[now].begin(), v[now].end(), le);
		}
		int mid = (l + r) >> 1;
		return query(tl, tr, le, ri, now * 2 + 1, l, mid) + query(tl, tr, le, ri, now * 2 + 2, mid, r);
	}
	
};

std::vector <int> check_validity(int n, std::vector <int> _u, std::vector <int> _v,
std::vector <int> s, std::vector <int> e, std::vector <int> l, std::vector <int> r) {
	int m = _u.size();
	int q = s.size();
	std::vector <std::vector <int>> g(n), ql(n), qr(n);
	std::vector <int> pl(q), pr(q), tord(n), initial(n), ans(q);
	Dsu dsul(n), dsur(n);
	for (int i = 0; i < m; i++) {
		g[_u[i]].push_back(_v[i]);
		g[_v[i]].push_back(_u[i]);
	}
	for (int i = 0; i < q; i++) {
		ql[l[i]].push_back(i);
		qr[r[i]].push_back(i);
	}
	for (int i = 0; i < n; i++) {
		for (int x : g[n - i - 1]) {
			if (x > n - i - 1) {
				dsul.unite(n - i - 1, x);
			}
		}
		for (int x : ql[n - i - 1]) {
			pl[x] = dsul.find(s[x]);
		}
		for (int x : g[i]) {
			if (x < i) {
				dsur.unite(i, x);
			}
		}
		for (int x : qr[i]) {
			pr[x] = dsur.find(e[x]);
		}
	}
	dsul.make(dsul.find(0));
	dsur.make(dsur.find(0));
	for (int i = 0; i < n; i++) {
		tord[dsul.tour[i]] = i;
	}
	for (int i = 0; i < n; i++) {
		initial[i] = tord[dsur.tour[i]];
	}
	Rag rag(initial);
	for (int i = 0; i < q; i++) {
		ans[i] = !!rag.query(dsur.l[pr[i]], dsur.r[pr[i]], dsul.l[pl[i]], dsul.r[pl[i]]);
	}
	return 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...