# [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);
for (int i = 1; i <= n; 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