P4254 [JSOI2008]Blue Mary开公司(李超线段树模板)

洛谷链接

题目大意就是 q 个询问,每次插入一条直线,或询问 横坐标 x x x 处最高点的 y y y 值是多少。

李超线段树模板题,李超线段树用来维护二维平面的直线(线段),线段树上每一个节点维护覆盖这个区间的最优势线段(即在 m i d mid mid 处取值最大的线段),类似于线段树分治,每条线段在线段树上拆分成 l o g log log 段,更新不会用 pushdown 下推标记(原来这个东西叫标记永久化),单点询问返回路径上的线段在 x x x 处的最大值。

细节学习参考:李超树学习博客


代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e4 + 10;
const int N = 5e4;
int q;
char op[20];
struct Line {
    
    				//线段结构体 
	double k,b;				 
	int l,r;				//这条线段的区间
	Line() {
    
    }
	Line(int x,int y,double ki,double bi) {
    
    
		l = x, r = y;
		k = ki, b = bi;
	}
	double calc(int x) {
    
    	//计算在 x 点的 y值 
		return k * x + b;
	}
};
struct seg_tree {
    
    
	#define lson rt << 1,l,mid
	#define rson rt << 1 | 1,mid + 1,r
	int tag[maxn << 2];
	Line line[maxn << 2];
	void build(int rt,int l,int r) {
    
    
		tag[rt] = 0; line[rt].k = line[rt].b = 0;
		if (l == r) return ;
		int mid = l + r >> 1;
		build(lson); build(rson);
	}
	void update(int rt,int l,int r,Line t) {
    
    
		if (t.l <= l && r <= t.r) {
    
    
			if (!tag[rt]) {
    
    									//还没有优势线段 
				tag[rt] = 1;
				line[rt] = t;
			} else if (line[rt].calc(l) < t.calc(l) && line[rt].calc(r) < t.calc(r)) {
    
    		//完全覆盖当前的优势线段 
				line[rt] = t;
			} else if (line[rt].calc(l) < t.calc(l) || line[rt].calc(r) < t.calc(r)) {
    
    		//有一端覆盖 
				int mid = l + r >> 1;
				if (line[rt].calc(mid) < t.calc(mid)) {
    
    					//现在t一定是比较不优的线段 
					Line tmp = t; t = line[rt]; line[rt] = tmp;
				}
				if (t.k < line[rt].k) {
    
    						//左端点还有贡献的机会,就往左端点 
					update(lson,t);
				} else {
    
    									//如果右端点还有贡献的机会,就往右端点 
					update(rson,t);
				}
			}
		} else {
    
    
			int mid = l + r >> 1;
			if (t.l <= mid) update(lson,t);
			if (mid + 1 <= t.r) update(rson,t);
		}
	}
	double query(int rt,int l,int r,int v) {
    
    		//查询在 v 点的最优势线段的取值 
		if (l == r) return line[rt].calc(v);
		double ans = line[rt].calc(v);				//当前区间的最优势线段在 v 点的取值 
		int mid = l + r >> 1;
		if (v <= mid) ans = max(ans,query(lson,v));
		else ans = max(ans,query(rson,v));
		return ans;
	}
}seg;
int main() {
    
    
	seg.build(1,1,N);
	scanf("%d",&q);
	while (q--) {
    
    
		scanf("%s",op);
		if (op[0] == 'Q') {
    
    
			int x; scanf("%d",&x);
			printf("%d\n",(int) (seg.query(1,1,N,x) / 100));
		} else {
    
    
			double k,b; scanf("%lf%lf",&b,&k);
			b -= k;							//起点是 x = 1,b要减去 k
			seg.update(1,1,N,Line(1,N,k,b));
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41997978/article/details/104617612
今日推荐