1 条题解

  • 0
    @ 2026-4-23 2:06:29

    #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

    「ICPC World Finals 2019」雨落葡萄园

    信息

    ID
    8517
    时间
    10000ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者