bzoj1568 [JSOI2008]Blue Mary开公司
分析
这是一道李超树的板子题
李超树是解决区间加直线的一种数据结构,具体操作和线段树很想
对于每插入一条直线,如果严格大于或小于如何处理便很明显了
如果有交点,则现在节点对应的区间存在此区间占比例大的那一条直线
然后递归到交点所在到那半个区间进行处理
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
char s[110];
double k[200000],b[200000],Ans;
int is[200000];
inline double get(double b1,double k1,double b2,double k2){return (b2-b1)/(k1-k2);}
inline void add(int le,int ri,int wh,double B,double K){
if(!is[wh]){
k[wh]=K;
b[wh]=B;
is[wh]=1;
return;
}
double f1=K*le+B,f2=k[wh]*le+b[wh],f3=K*ri+B,f4=k[wh]*ri+b[wh];
if(f1<=f2&&f3<=f4)return;
if(f1>=f2&&f3>=f4)k[wh]=K,b[wh]=B;
else {
int mid=(le+ri)>>1;
double x=get(B,K,b[wh],k[wh]);
if(f1>=f2){
if(x<=mid)add(le,mid,wh<<1,B,K);
else add(mid+1,ri,wh<<1|1,b[wh],k[wh]),k[wh]=K,b[wh]=B;
}else {
if(x>mid)add(mid+1,ri,wh<<1|1,B,K);
else add(le,mid,wh<<1,b[wh],k[wh]),k[wh]=K,b[wh]=B;
}
}
}
inline void q(int le,int ri,int wh,int x){
if(is[wh])Ans=max(Ans,x*k[wh]+b[wh]);
if(le==ri)return;
int mid=(le+ri)>>1;
if(mid>=x)q(le,mid,wh<<1,x);
else q(mid+1,ri,wh<<1|1,x);
}
int main(){
int n,m,i,j,k;
n=50000;
scanf("%d",&m);
while(m--){
int x;
double xx,yy;
scanf("%s",s);
if(s[0]=='P')scanf("%lf%lf",&xx,&yy),add(1,n,1,xx-yy,yy);
else scanf("%d",&x),Ans=0,q(1,n,1,x),printf("%lld\n",(long long)(Ans/100));
}
return 0;
}