模板题:BZOJ : 1568: [JSOI2008]Blue Mary开公司
给定若干条直线,求在x=x0处(x0为正整数)y的最大值。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<cmath>
#define ll long long
#define llu unsigned ll
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int maxn=50050;
const int n=50000;
struct node
{
    double k,b;
    int l,r,flag;
}t[maxn<<2];

double cross(double k1,double b1,double k2,double b2)
{
    return (b2-b1)/(k1-k2);
}

void build(int l,int r,int cnt)
{
    t[cnt].l=l,t[cnt].r=r;
    t[cnt].k=t[cnt].b=0;
    t[cnt].flag=0;
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(l,mid,cnt<<1);
    build(mid+1,r,cnt<<1|1);
}

void change(double k,double b,int cnt)
{
    if(!t[cnt].flag)
    {
        t[cnt].k=k,t[cnt].b=b;
        t[cnt].flag=1;
        return ;
    }
    //如果能l==r的话,在这一点y值一定可比较,而不会向下更新。
    double y1=k*t[cnt].l+b,y2=k*t[cnt].r+b;
    double y3=t[cnt].k*t[cnt].l+t[cnt].b,y4=t[cnt].k*t[cnt].r+t[cnt].b;
    if(y1<=y3&&y2<=y4) return ;
    if(y1>=y3&&y2>=y4)
    {
        t[cnt].k=k,t[cnt].b=b;
        return ;
    }
    double posx=cross(k,b,t[cnt].k,t[cnt].b);
    if(posx<=t[cnt<<1].r)
    {
        if(y1>=y3) change(k,b,cnt<<1);
        else
        {
            change(t[cnt].k,t[cnt].b,cnt<<1);
            t[cnt].k=k,t[cnt].b=b;
        }
    }
    else
    {
        if(y1>=y3)
        {
            change(t[cnt].k,t[cnt].b,cnt<<1|1);
            t[cnt].k=k,t[cnt].b=b;
        }
        else change(k,b,cnt<<1|1);
    }
}

double ans;
void ask(int pos,int cnt)
{
    if(t[cnt].flag) ans=max(ans,t[cnt].k*pos+t[cnt].b);
    if(t[cnt].l==t[cnt].r) return ;
    if(pos<=t[cnt<<1].r) ask(pos,cnt<<1);
    else ask(pos,cnt<<1|1);
}

int main(void)
{
   char op[20];
   int p,x;
   double k,b;
   build(1,n,1);
   scanf("%d",&p);
   for(int i=1;i<=p;i++)
   {
       scanf("%s",op);
       if(op[0]=='P')
       {
           scanf("%lf%lf",&b,&k);
           change(k,b-k,1);
       }
       else
       {
           scanf("%d",&x);
           ans=0;
           ask(x,1);
           printf("%lld\n",(ll)(ans/100));
       }
   }
   return 0;
}