Submission #425597

#TimeUsernameProblemLanguageResultExecution timeMemory
425597MlxaComparing Plants (IOI20_plants)C++14
0 / 100
4088 ms5236 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(x) x.begin(), x.end()
#define mp make_pair
#define mt make_tuple
#define x first
#define y second
#include "plants.h"


namespace my {
const int N = 303;
int n, k, kth[N], can[N];
vector<int> g[N];

struct tree_t {
	pair<int, int> arr[N];
	void build() {
		for (int i = 0; i < N; ++i) {
			arr[i].x = kth[i];
			arr[i].y = i;
		}
	}
	void range_add(int l, int r, int value) {
		for (int i = l; i < r; ++i) {
			arr[i].x += value;
		}
	}
	void cycle_add(int from, int value) {
		from %= n; from += n; from %= n;
		if (from + k <= n) {
			range_add(from, from + k, value);
		} else {
			range_add(from, n, value), range_add(0, from + k - n, value);
		}
	}
	pair<int, int> range_min(int l, int r) {
		return *min_element(arr + l, arr + r);
	}
	pair<int, int> cycle_min(int from) {
		from %= n; from += n; from %= n;
		if (from + k <= n) {
			return range_min(from, from + k);
		} else {
			return min(range_min(from, n), range_min(0, from + k - n));
		}
	}
	int single(int i) {
		assert(0 <= i && i < n);
		return arr[i].x;
	}
} tree;

void edge(int v, int u) {
	assert(0 <= v && v < n);
	assert(0 <= u && u < n);
	// cout << "edge " << v << " " << u << endl;
	g[v].push_back(u);
}

vector<int> topsort;

void extract(int v) {
	tree.range_add(v, v + 1, N);
	while (1) {
		auto e = tree.cycle_min(v - k + 1);
		if (e.x) break;
		extract(e.y);
	}
	tree.cycle_add(v - k + 1, -1);
	topsort.push_back(v);
}


void bfs(int v, bool used[N]) {
	queue<int> q;
	q.push(v);
	used[v] = true;
	while (q.size()) {
		v = q.front(); q.pop();
		for (int u : g[v]) {
			if (!used[u]) {
				q.push(u);
				used[u] = true;
			}
		}
	}
}

bool reach[N][N];
int lef[N], rig[N];
}

void init(int _k, vector<int> _r) {
	using namespace my;
	n = (int)_r.size();
	k = _k;
	copy(all(_r), kth);
	tree.build();
	while (1) {
		auto e = tree.range_min(0, n);
		if (e.x) break;
		extract(e.y);
	}
	assert((int)topsort.size() == n);
	reverse(all(topsort));
	for (int i = 0; i < n; ++i) {
		can[topsort[i]] = i;
	}
	set<pair<int, int>> iset;
	for (int i = 0; i < k; ++i) {
		iset.emplace(can[i], i);
	}
	fill_n(lef, n, -1), fill_n(rig, n, -1);
	for (int i = k;;) {
		auto it = iset.lower_bound(mp(can[i], i));
		if (it != iset.end()) {
			rig[it->y] = i;
		}
		if (it != iset.begin()) {
			--it;
			lef[i] = it->y;
		}
		iset.erase({can[(i + n - k) % n], (i + n - k) % n});
		iset.emplace(can[i], i);
		(i += 1) %= n;
		if (i == k) break;
	}
	for (int i = 0; i < n; ++i) {
		// cout << i << " " << lef[i] << " " << rig[i] << endl;
		if (lef[i] != -1) {
			edge(i, lef[i]);
		}
		if (rig[i] != -1) {
			edge(i, rig[i]);
		}
	}
	for (int i = 0; i < n; ++i) {
		bfs(i, reach[i]);
	}
}

int compare_plants(int x, int y) {
	using namespace my;
	if (reach[x][y]) {
		return 1;
	} else if (reach[y][x]) {
		return -1;
	} else {
		return 0;
	}
}

#ifdef LC
#include "grader.cpp"
#endif
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...