Codeforces Round #660
Codeforces Round #660 https://codeforces.com/contest/1388 E 题意 平面上有一些线段,将他们投影到$x$轴上,使得彼此不想交(但是可以挨着),设最左边的点和最右边的点的横坐标分别是$x_l, x_r$, 求$min{x_r-x_l}$ Solution 首先对于两个线段$s_1, s_2$, 并且$s_1.y < s_2.y$, 交叉连接他们的左右端点,得到一个向量集合$bound$,对投影向量限制限制。 因此先两两枚举,得到投影向量的可行的取值。 而且最优的投影向量,是集合$bound$中的某一项 因此,对剩下的可行的投影向量, 假设当前枚举的方向是$k_i$,计算 $$ max{x_j+y_jKi}-min{x_j+y_jk_i} $$ 计算这个式子可以用Convex hull trick, 然后不断更新ans #include <cstdio> #include <stack> #include <set> #include <cmath> #include <map> #include <time.h> #include <vector> #include <iostream> #include <string> #include <cstring> #include <algorithm> #include <memory.h> #include <cstdlib> #include <queue> #include <iomanip> #include <bitset> #include <unordered_map> #include <assert.h> #include <list> #define P pair<int, int> #define LL long long #define LD long double #define PLL pair<LL, LL> #define mset(a, b) memset(a, b, sizeof(a)) #define rep(i, a, b) for (int i = a; i < b; i++) #define PI acos(-1.0) #define random(x) rand() % x #define debug(x) cout << #x << " " << x << "\n" using namespace std; const int inf = 0x3f3f3f3f; const LL __64inf = 0x3f3f3f3f3f3f3f3f; #ifdef DEBUG const int MAX = 1e3 + 50; #else const int MAX = 1e6 + 50; #endif const int mod = 998244353; void file_read(){ #ifdef DEBUG freopen64("in", "r", stdin); #endif } struct Seg { double xl, xr, y; Seg(double xl, double xr, double y) : xl(xl), xr(xr), y(y) {} }; vector<Seg> seg; vector<pair<double, double>> bd; void bound() { for(int i = 0; i < seg.size(); i++) { for(int j = i+1; j < seg.size(); j++) { if(seg[i].y == seg[j].y) continue; auto s1 = seg[i]; auto s2 = seg[j]; if(s1.y > s2.y) swap(s1, s2); double beta1 = (s1.xr - s2.xl) / (s2.y - s1.y); double beta2 = (s1.xl - s2.xr) / (s2.y - s1.y); bd.emplace_back(beta2, beta1); } } } void filter(vector<double> &theta) { double cur = -__64inf; for(auto x : bd) { if(x.first >= cur) { theta.push_back(x.first); if(cur > -__64inf) theta.push_back(cur); } cur = max(cur, x.second); } theta.push_back(cur); } double cross(pair<double, double> A, pair<double, double> B) { return (A.first - B.first) / (B.second - A.second); } template<typename Cmp_1, typename Cmp_2> struct Convex { int top; vector<pair<double, double>> pts; vector<double> X; pair<double, double> stk[3000]; Cmp_1 cmp_1; Cmp_2 cmp_2; Convex(vector<Seg> &seg) : cmp_1(Cmp_1()), cmp_2(Cmp_2()) { for(auto s : seg) { pts.emplace_back(s.xl, s.y); pts.emplace_back(s.xr, s.y); } sort(pts.begin(), pts.end(), [this](const pair<double, double> &A, const pair<double, double> &B){ if(abs(A.second - B.second) < 1e-8 ) return this->cmp_1(A.first, B.first);//return A.first < B.first; // return A.second > B.second; return this->cmp_2(A.second, B.second); }); int i = 0; top = 0; stk[top++] = pts[0]; while(i < pts.size() and abs(pts[i].second-pts[0].second) < 1e-8) i++; if(i == pts.size()) { X.push_back(-__64inf); return ; } stk[top++] = pts[i++]; while(i < pts.size()) { int j = i; while(j < pts.size() and abs(pts[j].second-pts[i].second) < 1e-8) j++; if(j == pts.size()) break; auto cur = pts[j]; while(top >= 2) { double cross_x = cross(stk[top-1], stk[top-2]); double cross_cur = cross(cur, stk[top-2]); if(cross_cur < cross_x) top--; else break; } stk[top++] = cur; i = j+1; } X.push_back(-__64inf); for(int i = 1; i < top; i++) { X.push_back(cross(stk[i-1], stk[i])); } } double query(double a) { int idx = lower_bound(X.begin(), X.end(), a)- X.begin(); idx--; return stk[idx].first + stk[idx].second * a; } }; struct Less { bool operator () (double A, double B) { return A < B; } }; struct Great { bool operator () (double A, double B) { return A > B; } }; int main(){ #ifdef DEBUG freopen64("in", "r", stdin); #endif int n; scanf("%d", &n); set<double> Y; for(int i = 0; i < n; i++) { double xl, xr, y; scanf("%lf%lf%lf", &xl, &xr, &y) ; seg.emplace_back(xl, xr, y); Y.insert(y); } if(Y.size() == 1) { double Min = __64inf, Max = -__64inf; for(auto s : seg) { Min = min(s.xl, Min); Max = max(Max, s.xr); } printf("%.10f\n", Max-Min); return 0; } bound(); vector<double> theta; sort(bd.begin(), bd.end()); filter(theta); #ifdef DEBUG for(auto t : theta) printf("%.2f ", t); puts(""); #endif double ans = __64inf; Convex<Less, Great> left(seg); Convex<Great, Less> right(seg); for(auto x : theta) { double l = left.query(x); double r = right.query(x); ans = min(ans, r-l); } printf("%.10f\n", ans); } A B C D A B C D ...