• 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 << "
    "
    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
    ", 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
    ", ans);
    }
    

    A B C D

    A
    B
    C
    D

  • 相关阅读:
    T-Sql语法:行转列(pivot)和列转行(unpivot)
    T-Sql语法:GROUP BY子句GROUPING SETS、CUBE、ROLLUP
    Asp.net使用Plupload上传组件详解
    form标签属性enctype之multipart/form-data请求详解
    基于Owin Oauth2构建授权服务器
    AutoFac使用~IOC容器(DIP,IOC,DI)
    第二节:模型(Models)和管理后台(Admin site)
    第三节:视图(Views)和模板(Templates)
    THINKPHP 3.2 PHP SFTP上传下载 代码实现方法
    Linux 上导出导入sql文件到服务器命令
  • 原文地址:https://www.cnblogs.com/sidolarry/p/13488315.html
Copyright © 2020-2023  润新知