#include <bits/stdc++.h>
using namespace std;
using i = int;
const i MOD = 30013;
struct Seg {
i mx;
i cnt;
Seg(i m=0, i c=0): mx(m), cnt(c) {}
};
Seg mergeSeg(const Seg &a, const Seg &b) {
if (a.mx > b.mx) return a;
if (b.mx > a.mx) return b;
if (a.mx == 0) return Seg(0, 1);
return Seg(a.mx, (a.cnt + b.cnt) % MOD);
}
struct ST {
i n;
vector<Seg> t;
ST(i _n): n(_n), t(4*_n+4, Seg(0, 1)) {}
Seg queryRec(i p, i l, i r, i ql, i qr) {
if (r < ql || l > qr) return Seg(0, 1);
if (ql <= l && r <= qr) return t[p];
i m = (l + r) >> 1;
return mergeSeg(
queryRec(p<<1, l, m, ql, qr),
queryRec(p<<1|1, m+1, r, ql, qr)
);
}
Seg query(i left, i right) {
return left > right ? Seg(0, 1) : queryRec(1, 1, n, left, right);
}
void updateRec(i p, i l, i r, i pos, const Seg &val) {
if (l == r) {
t[p] = mergeSeg(t[p], val);
return;
}
i m = (l + r) >> 1;
if (pos <= m) updateRec(p<<1, l, m, pos, val);
else updateRec(p<<1|1, m+1, r, pos, val);
t[p] = mergeSeg(t[p<<1], t[p<<1|1]);
}
void update(i pos, const Seg &val) {
updateRec(1, 1, n, pos, val);
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
i N;
cin >> N;
struct Trap { i a, b, c, d; };
vector<Trap> A(N);
vector<i> coords;
coords.reserve(4 * N);
for (i idx = 0; idx < N; idx++) {
cin >> A[idx].a >> A[idx].b >> A[idx].c >> A[idx].d;
coords.push_back(A[idx].a);
coords.push_back(A[idx].b);
coords.push_back(A[idx].c);
coords.push_back(A[idx].d);
}
sort(coords.begin(), coords.end());
coords.erase(unique(coords.begin(), coords.end()), coords.end());
auto getId = [&](i v) {
return (i)(lower_bound(coords.begin(), coords.end(), v) - coords.begin() + 1);
};
i M = coords.size();
for (auto &t : A) {
t.a = getId(t.a);
t.b = getId(t.b);
t.c = getId(t.c);
t.d = getId(t.d);
}
sort(A.begin(), A.end(), [](const Trap &u, const Trap &v) {
return u.a != v.a ? u.a < v.a : u.b < v.b;
});
ST stTop(M), stBot(M);
vector<Seg> dp(N);
for (i idx = 0; idx < N; idx++) {
Seg leftBest = stTop.query(1, A[idx].a - 1);
Seg downBest = stBot.query(1, A[idx].c - 1);
Seg best = mergeSeg(leftBest, downBest);
dp[idx] = Seg(best.mx + 1, best.cnt);
stTop.update(A[idx].b, dp[idx]);
stBot.update(A[idx].d, dp[idx]);
}
i maxLen = 0;
for (auto &s : dp) maxLen = max(maxLen, s.mx);
i ways = 0;
for (auto &s : dp) if (s.mx == maxLen) ways = (ways + s.cnt) % MOD;
cout << maxLen << " " << ways;
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |