李超线段树 - JSOI2008BlueMary开公司

Posted starusc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了李超线段树 - JSOI2008BlueMary开公司相关的知识,希望对你有一定的参考价值。

李超线段树用来在平面内动态插入线段,求\\(x=t\\)直线与这些线段交点的最值

核心是维护每个区间的“最优势线段”,即终点位置处最高的线段,询问室对所有包含\\(t\\)的区间的最优势线段计算答案,最后取\\(max\\)

模板题:JSOI2008BlueMary开公司

插入直线,求单点最大值

(看代码)

#include<bits/stdc++.h>
using namespace std;
const int N=50004;
#define lc (p<<1)
#define rc (p<<1|1)
int n=50000,Q;
char s[20];
double tk[N<<2],tb[N<<2];
bool tfl[N<<2];
void modify(int p,int l,int r,double k,double b){
	if(!tfl[p]){tfl[p]=1;tk[p]=k;tb[p]=b;return;}
	int mid=l+r>>1;
	double l1=l*k+b,r1=r*k+b;
	double l2=l*tk[p]+tb[p],r2=r*tk[p]+tb[p];
	if(l1<=l2&&r1<=r2)return;
	if(l1>l2&&r1>r2){tk[p]=k;tb[p]=b;return;}
	double x=(b-tb[p])/(tk[p]-k);
	if(l1>l2){
		if(x>mid){
			modify(rc,mid+1,r,tk[p],tb[p]);
			tk[p]=k;tb[p]=b;
		}
		else modify(lc,l,mid,k,b);
	}
	else{
		if(x>mid)modify(rc,mid+1,r,k,b);
		else{
			modify(lc,l,mid,tk[p],tb[p]);
			tk[p]=k;tb[p]=b;
		}
	}
}
double query(int p,int l,int r,int x){
	if(l==r)return tk[p]*x+tb[p];
	int mid=l+r>>1;
	double ret=tk[p]*x+tb[p];
	if(x<=mid)return max(ret,query(lc,l,mid,x));
	else return max(ret,query(rc,mid+1,r,x)); 
}
int main(){
	scanf("%d",&Q);
	while(Q--){
		scanf("%s",s);
		if(s[0]==\'P\'){
			static double x,y;
			scanf("%lf%lf",&x,&y);
			modify(1,1,n,y,x-y);
		} 
		else{
			static int x;
			scanf("%d",&x);
			cout<<(long long)(query(1,1,n,x)/100)<<"\\n";
		}
	} 
	return (0-0);
}

以上是关于李超线段树 - JSOI2008BlueMary开公司的主要内容,如果未能解决你的问题,请参考以下文章

1568: [JSOI2008]Blue Mary开公司

BZOJ1568[JSOI2008]Blue Mary开公司 线段树

BZOJ 1568: [JSOI2008]Blue Mary开公司(超哥线段树)

bzoj 1568 [JSOI2008]Blue Mary开公司 超哥线段树

Blue Mary开公司题解

bzoj1568 [JSOI2008]Blue Mary开公司