zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    flume sink两种类型 file_rool 自定义sing com.mycomm.MySink even if there is only one event, the event has to be sent in an array
    为什么引入进程20年后,又引入线程?
    As of Flume 1.4.0, Avro is the default RPC protocol.
    Google Protocol Buffer 的使用和原理
    Log4j 2
    统一日志 统一订单
    网站行为跟踪 Website Activity Tracking Log Aggregation 日志聚合 In comparison to log-centric systems like Scribe or Flume
    Percolator
    友盟吴磊:移动大数据平台的架构、实践与数据增值
    Twitter的RPC框架Finagle简介
  • 原文地址:https://www.cnblogs.com/sidolarry/p/13488315.html
Copyright © 2011-2022 走看看