[school training 2019-05-22] prediction

[main ideas]

  • First of all, use the hall hall theorem + + + line tree to judge whether there is a solution.
  • If there is a solution, consider constructing the solution with the least lexicographic order from the front to the back.
  • Since filling in a number at a POS POS POS will only affect the interval with the left end as pospospos, you can divide the right end ritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritritrit.
  • Then a line tree is used to maintain the minimum number of the right end point in the interval.
  • Time complexity O(NLog2N)O(NLog^2N)O(NLog2N). If it is changed to bisection on the line tree, time complexity is O(NLogN)O(NLogN)O(NLogN).

[Code]

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5;
const int INF = 1e9;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
template <typename T> void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
	write(x);
	puts("");
}
struct MainSegmentTree {
	struct Node {
		int lc, rc;
		int Min, tag;
	} a[MAXN * 2];
	int n, size, root;
	void update(int root) {
		a[root].Min = min(a[a[root].lc].Min, a[a[root].rc].Min);
	}
	void build(int &root, int l, int r) {
		root = ++size;
		a[root].Min = l;
		if (l == r) return;
		int mid = (l + r) / 2;
		build(a[root].lc, l, mid);
		build(a[root].rc, mid + 1, r);
		update(root);
	}
	void init(int x) {
		n = x;
		root = size = 0;
		build(root, 1, n);
	}
	void pushdown(int root) {
		if (a[root].tag) {
			a[a[root].lc].Min += a[root].tag;
			a[a[root].lc].tag += a[root].tag;
			a[a[root].rc].Min += a[root].tag;
			a[a[root].rc].tag += a[root].tag;
			a[root].tag = 0;
		}
	}
	void modify(int root, int l, int r, int ql, int qr, int d) {
		if (l == ql && r == qr) {
			a[root].Min += d;
			a[root].tag += d;
			return;
		}
		pushdown(root);
		int mid = (l + r) / 2;
		if (mid >= ql) modify(a[root].lc, l, mid, ql, min(qr, mid), d);
		if (mid + 1 <= qr) modify(a[root].rc, mid + 1, r, max(mid + 1, ql), qr, d);
		update(root);
	}
	void modify(int l, int r, int d) {
		if (l > r) return;
		else modify(root, 1, n, l, r, d);
	}
	int queryMin(int root, int l, int r, int ql, int qr) {
		if (l == ql && r == qr) return a[root].Min;
		pushdown(root);
		int mid = (l + r) / 2, ans = INF;
		if (mid >= ql) chkmin(ans, queryMin(a[root].lc, l, mid, ql, min(mid, qr)));
		if (mid + 1 <= qr) chkmin(ans, queryMin(a[root].rc, mid + 1, r, max(mid + 1, ql), qr));
		return ans;
	}
	int queryMin(int l, int r) {
		if (l > r) return 0;
		else return queryMin(root, 1, n, l, r);
	}
} MST;
struct AuxSegmentTree {
	struct Node {
		int lc, rc;
		int Min;
	} a[MAXN * 2];
	set <int> st[MAXN];
	int n, size, root;
	void update(int root) {
		a[root].Min = min(a[a[root].lc].Min, a[a[root].rc].Min);
	}
	void build(int &root, int l, int r) {
		root = ++size;
		a[root].Min = INF;
		if (l == r) return;
		int mid = (l + r) / 2;
		build(a[root].lc, l, mid);
		build(a[root].rc, mid + 1, r);
		update(root);
	}
	void init(int x) {
		n = x;
		root = size = 0;
		build(root, 1, n);
	}
	void modify(int root, int l, int r, int x, int d) {
		if (l == r) {
			if (d >= 0) st[l].insert(d);
			else st[l].erase(-d);
			if (st[l].size()) a[root].Min = *st[l].begin();
			else a[root].Min = INF;
			return;
		}
		int mid = (l + r) / 2;
		if (mid >= x) modify(a[root].lc, l, mid, x, d);
		else modify(a[root].rc, mid + 1, r, x, d);
		update(root);
	}
	void modify(int x, int d) {
		modify(root, 1, n, x, d);
	}
	int queryMin(int root, int l, int r, int ql, int qr) {
		if (l == ql && r == qr) return a[root].Min;
		int mid = (l + r) / 2, ans = INF;
		if (mid >= ql) chkmin(ans, queryMin(a[root].lc, l, mid, ql, min(mid, qr)));
		if (mid + 1 <= qr) chkmin(ans, queryMin(a[root].rc, mid + 1, r, max(mid + 1, ql), qr));
		return ans;
	}
	int queryMin(int l, int r) {
		if (l > r) return 0;
		else return queryMin(root, 1, n, l, r);
	}
} AST;
int n, x[MAXN], y[MAXN];
void checkSolution() {
	static vector <int> a[MAXN];
	for (int i = 1; i <= n; i++)
		a[x[i]].push_back(y[i]);
	MST.init(n);
	for (int i = n; i >= 1; i--) {
		for (auto x : a[i])
			MST.modify(x, n, -1);
		int tmp = MST.queryMin(i, n);
		if (tmp - i + 1 < 0) {
			puts("-1");
			exit(0);
		}
	}
}
int main() {
	freopen("prophesy.in", "r", stdin);
	freopen("prophesy.out", "w", stdout);
	read(n);
	for (int i = 1; i <= n; i++)
		read(x[i]), read(y[i]);
	checkSolution();
	AST.init(n);
	static vector <int> a[MAXN];
	for (int i = 1; i <= n; i++)
		a[x[i]].push_back(i);
	for (int i = 1; i <= n; i++) {
		for (auto x : a[i])
			AST.modify(y[x], x);
		int l = i, r = n;
		while (l < r) {
			int mid = (l + r) / 2;
			if (MST.queryMin(i, mid) - i + 1 == 0) r = mid;
			else l = mid + 1;
		}
		int ans = AST.queryMin(i, l);
		printf("%d ", ans);
		AST.modify(y[ans], -ans);
		MST.modify(y[ans], n, 1);
	}
	return 0;
}

Posted on Tue, 05 Nov 2019 14:38:29 -0500 by MrCreeky