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
",(long long)(Ans/100));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yzxverygood/p/10328784.html