zoukankan      html  css  js  c++  java
  • bzoj 1568 李超线段树

    博客:http://www.cnblogs.com/mangoyang/p/9979465.html

    李超线段树支持两种操作:1:插入一条直线。2:询问在x = c与这些直线的交点中最大的y坐标。

    插入的时候,如果有交点,本层节点留下来的是优势直线,劣势的那条去递归比较。优势直线是指在这个区间中覆盖的面积最大的那条直线。

    维护的时候用了标记永久化,所以递归询问回溯的时候比较所有的直线,取坐标最大的那一条。

    复杂度O(n(lgn)^2),常数相对于平衡树比较小。

    代码:

    #include <bits/stdc++.h>
    #define ls(x) (x << 1)
    #define rs(x) ((x << 1) | 1)
    using namespace std;
    const int maxn = 100010;
    struct line {
    	double k, b;
    };
    line a[maxn];
    int tot;
    struct SegementTree {
    	int id;
    };
    SegementTree tr[maxn * 4];
    double get_pos(int x, int y) {
    	return a[x].k * y + a[x].b;
    }
    double cross(int x, int y) {
    	return (a[x].b - a[y].b) / (a[y].k - a[x].k);
    }
    void update(int o, int l, int r, int now) {
    	if(!tr[o].id) {
    		tr[o].id = now;
    		return;
    	}
    	int x = tr[o].id;
    	double l1 = get_pos(now, l), r1 = get_pos(now, r);
    	double l2 = get_pos(x, l), r2 = get_pos(x, r);
    	if(l1 <= l2 && r1 <= r2) {
    		return;
    	}
    	else if(l1 > l2 && r1 > r2) {
    		tr[o].id = now;
    		return;
    	}
    	int mid = (l + r) >> 1;
    	double y = cross(now, x);
    	if(y <= mid) update(ls(o), l, mid, r1 > r2 ? x : now);
    	else update(rs(o), mid + 1, r, l1 > l2 ? x : now);
    	if((y <= mid && r1 > r2) || (y > mid && l1 > l2))
    		tr[o].id = now;
    }
    int query(int o, int l, int r, int pos) {
    	if(l == r) {
    		return tr[o].id;
    	}
    	int mid = (l + r) >> 1, ans = 0;
    	if(pos <= mid) ans = query(ls(o), l, mid, pos);
    	else ans = query(rs(o), mid + 1, r, pos);
    	if(!tr[o].id) return ans;
    	int x = tr[o].id;
    	if(get_pos(x, pos) > get_pos(ans, pos)) return x;
    	else return ans;
    }
    char s[110];
    int main() {
    	int n;
    	double x, y;
    	int z;
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++) {
    		scanf("%s",s + 1);
    		if(s[1] == 'P') {
    			scanf("%lf%lf", &x, &y);
    			a[++tot] = (line){y, x};
    			update(1, 0, 50000, tot);
    		} else {
    			scanf("%d", &z);
    			int ans = query(1, 0, 50000, z - 1);
    			printf("%d
    ", (int)(get_pos(ans, z - 1) / 100));
    		}
    	}
    } 
    

      

  • 相关阅读:
    img的srcset和sizes属性作用
    屏幕尺寸,分辨率,像素,PPI之间到底什么关系
    img 的 srcset、sizes 属性和 picture 元素
    收房细则
    购买雅居乐湖居笔记不得不知。
    Andoird Studio 错误: 非法字符: 'ufeff' 解决方案。
    解决mysql 1040错误Too many connections的方法
    Android布局优化之include、merge、ViewStub的使用
    美国人、英国人、中国人一生都是如何度过
    Android常用正则工具类
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/10595522.html
Copyright © 2011-2022 走看看