Submission #388408

#TimeUsernameProblemLanguageResultExecution timeMemory
388408moratoWerewolf (IOI18_werewolf)C++17
100 / 100
1280 ms212888 KiB
#include <bits/stdc++.h>
#include "werewolf.h"

using namespace std;

const int MAXL = 20;
const int INF = 1e9;
const int MAXN = 4e5 + 5;

class FenwickTree
{
	public:

		FenwickTree(int _n = MAXN - 1) {
			n = _n;
			for (int i = 0; i <= n; i++) {
				bit[i] = 0;
			}
		}

		void update(int x, int val) {
			for (; x <= n; x += x & -x)
				bit[x] += val;
		}

		int query(int x) {
			int ans = 0;
			for (; x > 0; x -= x & -x) 
				ans += bit[x];
			return ans;
		}

	private:

		int n;

		int bit[MAXN];

} bit;

class KRT
{
	public:

		KRT(int _n = 0): n(_n) {
			curTimer = 0;
			for (int i = 1; i <= n; i++) {
				p[i] = i;
			}
		}

		void init(int _n) {
			n = _n;
			for (int i = 1; i <= n; i++) {
				p[i] = i;
			}
		}

		int getTin(int v) { return tin[v]; }
		int getTout(int v) { return tout[v]; }
		int getRoot(int v) { return p[v] == v ? v : p[v] = getRoot(p[v]); }

		void addEdge(int v, int u, int w, int flag) {
			v = getRoot(v);
			u = getRoot(u);
			if (u == v) return;
			++n;
			p[n] = p[u] = p[v] = n;
			adj[n].push_back(v);
			adj[n].push_back(u);
			anc[v][0] = anc[u][0] = {n, w};
            anc[n][0] = make_pair(n, (flag ? 0 : INF));
		}

		void dfs(int cur) {
			tin[cur] = ++curTimer;
			for (int viz : adj[cur]) {
				dfs(viz);
			}
			tout[cur] = curTimer;
		}

		int get(int a, int b, int flag) {
			return flag ? max(a, b) : min(a, b);
		}

		void buildKRT(int flag) {
			for (int d = 1; d < MAXL; d++) {
				for (int i = 1; i <= n; i++) {
					auto mid = anc[i][d - 1];
					auto target = anc[mid.first][d - 1];
					anc[i][d] = {target.first, get(mid.second, target.second, flag)};
				}
			}
			dfs(n);
		}

		bool compare(int limit, int value, int flag) {
			return flag ? limit >= value : limit <= value;
		}

		int goUp(int v, int limit, int flag) {
			for (int j = MAXL - 1; j >= 0; j--) {
				if (compare(limit, anc[v][j].second, flag)) {
					v = anc[v][j].first;
				}
			}
			return v;
		}

	private:

		int n;
		int curLen;
		int curTimer;

		int p[MAXN];
		int tin[MAXN];
		int tout[MAXN];

		vector<int> adj[MAXN];

		pair<int, int> anc[MAXN][MAXL];

} krtMin, krtMax;

struct Event
{
	int tipo, idx;
	int x, y;

	Event() {}

	Event(int _t, int _i, int _x, int _y): tipo(_t), idx(_i), x(_x), y(_y) {}

	bool operator <(const Event &e) const {
		if (x == e.x) return tipo < e.tipo;
		return x < e.x;
	}
};

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 n = N;
	krtMin.init(n);
	krtMax.init(n);
	vector<pair<int, pair<int, int>>> edges[2];
	int m = (int) X.size();
	for (int i = 0; i < m; i++) {
		X[i]++, Y[i]++;
		edges[0].push_back(make_pair(min(X[i], Y[i]), make_pair(X[i], Y[i])));
		edges[1].push_back(make_pair(max(X[i], Y[i]), make_pair(X[i], Y[i])));
	}
	for (int i : {0, 1}) {
		sort(edges[i].begin(), edges[i].end());
	}
    reverse(edges[0].begin(), edges[0].end());
	for (int i = 0; i < m; i++) {
		int w = edges[0][i].first;
		int v = edges[0][i].second.first;
		int u = edges[0][i].second.second;
		krtMin.addEdge(v, u, w, 0);
	}
	for (int i = 0; i < m; i++) {
		int w = edges[1][i].first;
		int v = edges[1][i].second.first;
		int u = edges[1][i].second.second;
		krtMax.addEdge(v, u, w, 1);
	}
	krtMin.buildKRT(0);
	krtMax.buildKRT(1);
	int q = (int) S.size();
	vector<Event> sweep;
	for (int i = 1; i <= n; i++) {
		int x = krtMax.getTin(i);
		int y = krtMin.getTin(i);
		sweep.emplace_back(0, -1, x, y);
	}
	vector<int> ans(q);
	for (int i = 0; i < q; i++) {
		S[i]++, E[i]++, L[i]++, R[i]++;
		int maxHuman = krtMin.goUp(S[i], L[i], 0);
		int maxWerewolf = krtMax.goUp(E[i], R[i], 1);
		int y1 = krtMin.getTin(maxHuman);
		int y2 = krtMin.getTout(maxHuman);
		int x1 = krtMax.getTin(maxWerewolf);
		int x2 = krtMax.getTout(maxWerewolf);
		sweep.emplace_back(1, i, x1 - 1, y2);
		sweep.emplace_back(1, i, x2, y1 - 1);
		sweep.emplace_back(2, i, x1 - 1, y1 - 1);
		sweep.emplace_back(2, i, x2, y2);
	}
	sort(sweep.begin(), sweep.end());
	for (auto event : sweep) {
		if (event.tipo == 0) {
			bit.update(event.y, 1);
		} else if (event.tipo == 1) {
			ans[event.idx] -= bit.query(event.y);
		} else {
			ans[event.idx] += bit.query(event.y);
		}
	}
	for (int& 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...