1 条题解
-
0

#include <bits/stdc++.h> #define EB push_back using std::cin; using std::cout; typedef unsigned int u32; typedef long long ll; typedef std::pair <int, int> pr; typedef std::tuple <int, int, int> tuple; const int N = 500054, M = N * 4, INF = 0x3f3f3f3f; struct segment { int x1, y1, x2, y2; friend std::istream & operator >> (std::istream &in, segment &B) {return in >> B.x1 >> B.y1 >> B.x2 >> B.y2;} } seg[N]; int n, m, E = 0, ans = INF; int to[M], first[N], next[M]; int deg[N], topo[N]; inline void down(int &x, const int y) {x > y ? x = y : 0;} inline int min(const int x, const int y) {return x < y ? x : y;} inline int max(const int x, const int y) {return x < y ? y : x;} inline void addedge(int u, int v) {to[++E] = v, next[E] = first[u], first[u] = E, ++deg[v];} void toposort() { int i, h, t = 0, x, y; for (i = 0; i < n; ++i) if (!deg[i]) topo[t++] = i; for (h = 0; h < t; ++h) for (i = first[x = topo[h]]; i; i = next[i]) if (!--deg[y = to[i]]) topo[t++] = y; assert(t == n); } namespace G { typedef bool (*cmpFn)(const int &, const int &); typedef std::set <int, cmpFn> set; struct sweepLine { int x, id; sweepLine (int x_ = 0., int id_ = 0) : x(x_), id(id_) {} inline bool operator < (const sweepLine &B) const {return x < B.x || (x == B.x && id > B.id);} } sl[2 * N]; int X; inline double getY(int id, int x0) { if (id == INT_MIN) return -INFINITY; if (id == INT_MAX) return INFINITY; return (double)((ll)seg[id].x1 * seg[id].y2 - (ll)seg[id].x2 * seg[id].y1 + (ll)x0 * (seg[id].y1 - seg[id].y2)) / (double)(seg[id].x1 - seg[id].x2); } inline bool slCmp(const int &x, const int &y) {return getY(x, X) < getY(y, X);} set s(slCmp); void main() { int i, j, l, r; set::iterator it; for (i = 0; i < n; ++i) std::tie(l, r) = std::minmax(seg[i].x1, seg[i].x2), sl[i] = sweepLine(l, i), sl[i + n] = sweepLine(r, i + n); std::sort(sl, sl + 2 * n), s.insert(INT_MIN), s.insert(INT_MAX); for (j = 0; j < 2 * n; ++j) { i = sl[j].id, X = sl[j].x; if (i < n) { it = s.lower_bound(i); if ((u32)*it < (u32)n) addedge(i, *it); if ((u32)*--it < (u32)n) addedge(*it, i); s.emplace_hint(it, i); } else s.erase(i - n); } } } namespace DC { int F[2 * N]; pr D[2 * N]; int Discretize(int n) { int i, cnt = 0; std::sort(D, D + n); for (i = 0; i < n; ++i) F[D[i].second] = (i && D[i].first == D[i - 1].first ? cnt - 1 : (D[cnt] = D[i], cnt++)); return cnt; } } namespace ST { #define segc int M = (L + R - 1) >> 1, lc = id << 1, rc = lc | 1 #define exist_pd if (~x[id].cov || x[id].add) push_down(x[id], x[lc], x[rc]) struct node {int min, max, cov, add; bool asc, desc;} x[2100000]; inline void update(node &ret, const node &l, const node &r) { ret.min = min(l.min, r.min), ret.max = max(l.max, r.max), ret.asc = l.asc && r.asc && l.max <= r.min, ret.desc = l.desc && r.desc && l.min >= r.max; } inline void cover(node &ret, int x) {ret.min = ret.max = ret.cov = x, ret.add = 0, ret.asc = ret.desc = true;} inline void add(node &ret, int x) {ret.min += x, ret.max += x, (~ret.cov ? ret.cov : ret.add) += x;} inline void push_down(node &ret, node &l, node &r) { if (~ret.cov) cover(l, ret.cov), cover(r, ret.cov), ret.cov = -1; else if (ret.add) add(l, ret.add), add(r, ret.add), ret.add = 0; } void build(int id, int L, int R, int ql, int qr) { x[id].cov = -1, x[id].add = 0; if (L == R) {x[id].min = x[id].max = (ql <= L && R <= qr ? 0 : INF), x[id].asc = x[id].desc = true; return;} segc; build(lc, L, M, ql, qr), build(rc, M + 1, R, ql, qr); update(x[id], x[lc], x[rc]); } void add(int id, int L, int R, int ql, int qr, int v) { if (ql <= L && R <= qr) return add(x[id], v); segc; exist_pd; if (ql <= M) add(lc, L, M, ql, qr, v); if (qr > M) add(rc, M + 1, R, ql, qr, v); update(x[id], x[lc], x[rc]); } int X; void __builtin_desc(int id, int L, int R) { if (X <= x[id].min) return cover(x[id], X); if (X >= x[id].max && x[id].desc) {X = x[id].min; return;} segc; exist_pd; __builtin_desc(lc, L, M), __builtin_desc(rc, M + 1, R), update(x[id], x[lc], x[rc]); } void desc(int id, int L, int R, int ql, int qr) { if (ql <= L && R <= qr) return __builtin_desc(id, L, R); segc; exist_pd; if (ql <= M) desc(lc, L, M, ql, qr); if (qr > M) desc(rc, M + 1, R, ql, qr); update(x[id], x[lc], x[rc]); } void __builtin_asc(int id, int L, int R) { if (X <= x[id].min) return cover(x[id], X); if (X >= x[id].max && x[id].asc) {X = x[id].min; return;} segc; exist_pd; __builtin_asc(rc, M + 1, R), __builtin_asc(lc, L, M); update(x[id], x[lc], x[rc]); } void asc(int id, int L, int R, int ql, int qr) { if (ql <= L && R <= qr) return __builtin_asc(id, L, R); segc; exist_pd; if (qr > M) asc(rc, M + 1, R, ql, qr); if (ql <= M) asc(lc, L, M, ql, qr); update(x[id], x[lc], x[rc]); } void sweep(int id, int L, int R, int ql, int qr) { if (L == R) return down(ans, x[id].min); segc; exist_pd; if (ql <= M) sweep(lc, L, M, ql, qr); if (qr > M) sweep(rc, M + 1, R, ql, qr); } } int main() { int i, x, L, R; std::ios::sync_with_stdio(false), cin.tie(NULL); cin >> L >> R >> n; for (i = 0; i < n; ++i) cin >> seg[i]; G::main(), toposort(); for (i = 0; i < n; ++i) DC::D[i] = pr(seg[i].x1, i), DC::D[i + n] = pr(seg[i].x2, i + n); DC::D[2 * n] = pr(L, 2 * n), DC::D[2 * n + 1] = pr(R, 2 * n + 1), m = DC::Discretize(2 * n + 2), L = DC::F[2 * n], R = DC::F[2 * n + 1], ST::build(1, 0, m, L + 1, R); for (i = 0; i < n; ++i) { x = topo[i], L = DC::F[x], R = DC::F[x + n], ST::X = INF; if (L < R) ST::add(1, 0, m, L + 1, R, 1), ST::desc(1, 0, m, L, R); else if (L > R) ST::add(1, 0, m, R + 1, L, 1), ST::asc(1, 0, m, R + 1, L + 1); else throw "daklqw"; } L = DC::F[2 * n], R = DC::F[2 * n + 1], ST::sweep(1, 0, m, L + 1, R), cout << ans << '\n'; return 0; }
- 1
信息
- ID
- 8517
- 时间
- 10000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者