zoukankan      html  css  js  c++  java
  • Luogu 4254 [JSOI2008]Blue Mary开公司

    BZOJ 1568

    学习了一波李超线段树。   

    大佬blog

    这个东西专门用来维护插入一条线段和区间/单点的最大/最小值。

    插入的时候讨论:

    1、如果当前结点上没有线段,那么直接插入。

    2、如果当前结点上的线段一定比要插入的线段优/劣,那么直接覆盖或者返回。

    3、如果当前结点上的线段和要插入的线段有交点,那么把优的部分比劣的部分多的线段放在当前结点上,然后把另一条线段下放给那个交点所在的儿子递归处理。

    时间复杂度$O(nlogn)$,但是有返回这个操作看上去就很快……

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef double db;
    typedef long long ll;
    
    const int N = 5e4 + 5;
    
    int n = (int)5e4, qn;
    
    template <typename T>
    inline void chkMax(T &x, T y) {
        if(y > x) x = y;
    }
    
    namespace SegT {
        struct Node {
            db lb, lk;
            bool cov;
        } s[N << 2];
        
        #define lc p << 1
        #define rc p << 1 | 1
        #define mid ((l + r) >> 1)
        #define lb s[p].lb
        #define lk s[p].lk
        #define cov s[p].cov
        
        void ins(int p, int l, int r, db b, db k) {
            if(!cov) {
                lb = b, lk = k, cov = 1;
                return;
            }
            
            db l1 = 1.0 * l * k + b, r1 = 1.0 * r * k + b;
            db l2 = 1.0 * l * lk + lb, r2 = 1.0 * r * lk + lb;
            
            if(l1 >= l2 && r1 >= r2) {
                lb = b, lk = k;
                return;
            }
            if(l1 <= l2 && r1 <= r2) return;
            
            db x = (b - lb) / (lk - k);
            if(l1 > l2) {
                if(x > mid) ins(rc, mid + 1, r, lb, lk), lb = b, lk = k;
                else ins(lc, l, mid, b, k);
            } else {
    /*            if(x <= mid) ins(lc, l, mid, lb, lk), lb = b, lk = k;
                else ins(rc, mid + 1, r, lb, lk);  */
                if(x > mid) ins(rc, mid + 1, r, b, k);
                else ins(lc, l, mid, lb, lk), lb = b, lk = k;
            }
        }
        
        db query(int p, int l, int r, int x) {
            if(l == r) return lk * x + lb;
            db res = lk * x + lb;
            if(x <= mid) chkMax(res, query(lc, l, mid, x));
            else chkMax(res, query(rc, mid + 1, r, x));
            return res;
        }
        
    } using namespace SegT;
    
    int main() {
        scanf("%d", &qn);
        for(char op[12]; qn--; ) {
            scanf("%s", op);
            if(op[0] == 'P') {
                db b, k;
                scanf("%lf%lf", &b, &k);
                b -= k;
                ins(1, 1, n, b, k);
            } else {
                int x; scanf("%d", &x);
                db ans = query(1, 1, n, x);
                printf("%lld
    ", (ll) (ans / 100.0));
            }
        }
        return 0;
    } 
    View Code
  • 相关阅读:
    Validate US Telephone Numbers
    7月份总结
    Arguments Optional
    Everything Be True
    手机开发网页模板(20140124)
    整站开发初始化
    switch滑动开关
    js 面向对象
    Bootstrap 导航栏
    Bootstrap 标签页
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/10073011.html
Copyright © 2011-2022 走看看