Submission #259182

#TimeUsernameProblemLanguageResultExecution timeMemory
259182atoizWerewolf (IOI18_werewolf)C++14
100 / 100
976 ms100712 KiB
#include "werewolf.h"
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <vector>
#include <functional>

using namespace std;

struct DSU
{
	int N;
	vector<int> A;
	DSU(int _N = 0): N(_N), A(N, -1) {};
	int get(int u) { return (A[u] < 0 ? u : A[u] = get(A[u])); }
	void set(int v, int u) { A[get(v)] = u; }
};

struct BIT
{
	int N;
	vector<int> A;
	BIT(int _N = 0): N(_N + 5), A(N, 0) {};
	void inc(int i)
	{
		for (; i < N; i += i & (-i)) ++A[i];
	}

	int get(int l, int r)
	{
		int ans = 0;
		for (--l; l > 0; l -= l & (-l)) ans -= A[l];
		for (; r > 0; r -= r & (-r)) ans += A[r];
		return ans;
	}
};

struct Tree : vector<vector<int>>
{
	int LG, N;
	vector<vector<int>> anc;

	Tree(int _N): N(_N) { assign(N, vector<int>()); }

	void build()
	{
		LG = __lg(N) + 1;
		anc.assign(LG, vector<int>(N, -1));
		for (int u = 0; u < N; ++u) for (int v : at(u)) anc[0][v] = u;
		for (int j = 1; j < LG; ++j) for (int u = 0; u < N; ++u) {
			anc[j][u] = (~anc[j - 1][u] ? anc[j - 1][anc[j - 1][u]] : -1);
		}
	}

	void findTour(int u, int &curTime, vector<int> &tin, vector<int> &tout)
	{
		tin[u] = ++curTime;
		for (int v : at(u)) findTour(v, curTime, tin, tout);
		tout[u] = curTime;
	}

	void solve(int u, BIT &bit, vector<vector<pair<int, int>>> &queries, vector<int> &ans, vector<int> &tin, vector<int> &tout)
	{
		for (auto &q : queries[u]) ans[q.second] = -bit.get(tin[q.first], tout[q.first]);
		bit.inc(tin[u]);
		for (int v : at(u)) solve(v, bit, queries, ans, tin, tout);
		for (auto &q : queries[u]) ans[q.second] += bit.get(tin[q.first], tout[q.first]);
	}
};

vector<int> check_validity(int N, vector<int> X, vector<int> Y, vector<int> S, vector<int> E, vector<int> L, vector<int> R)
{
	int M = (int) X.size(), Q = (int) S.size();
	vector<vector<int>> adj(N);
	for (int i = 0; i < M; ++i) adj[X[i]].push_back(i), adj[Y[i]].push_back(i);
	
	Tree startTree(N), finishTree(N);
	DSU dsu;

	dsu = DSU(N);
	for (int u = N - 1; u >= 0; --u) {
		for (int i : adj[u]) {
			int v = u ^ X[i] ^ Y[i];
			if (v > u) {
				if (dsu.get(v) == u) continue;
				// cout << "sta " << u << " -> " << dsu.get(v) << endl;
				startTree[u].push_back(dsu.get(v));
				dsu.set(v, u);
			}
		}
	}

	dsu = DSU(N);
	for (int u = 0; u < N; ++u) {
		for (int i : adj[u]) {
			int v = u ^ X[i] ^ Y[i];
			if (v < u) {
				if (dsu.get(v) == u) continue;
				// cout << "fin " << u << " -> " << dsu.get(v) << endl;
				finishTree[u].push_back(dsu.get(v));
				dsu.set(v, u);
			}
		}
	}

	finishTree.build(), startTree.build();

	vector<int> tin(N), tout(N);
	int curTime = 0;
	startTree.findTour(0, curTime, tin, tout);

	vector<vector<pair<int, int>>> queries(N);
	for (int q = 0; q < Q; ++q) {
		// cout << q << " = " << S[q] << ' ' << E[q] << endl;
		for (int j = __lg(N); j >= 0; --j) {
			if (~startTree.anc[j][S[q]] && startTree.anc[j][S[q]] >= L[q]) S[q] = startTree.anc[j][S[q]];
			if (~finishTree.anc[j][E[q]] && finishTree.anc[j][E[q]] <= R[q]) E[q] = finishTree.anc[j][E[q]];
		}
		assert(S[q] >= L[q] && E[q] <= R[q]);
		// cout << q << " = " << S[q] << ' ' << E[q] << endl;
		queries[E[q]].emplace_back(S[q], q);
	}
	BIT bit(N);
	vector<int> ans(Q, 0);
	finishTree.solve(N - 1, bit, queries, ans, tin, tout);

	// for (auto &x : ans) cout << "ans " << x << endl;
	for (auto &x : ans) x = !!x;
	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...