• BZOJ 1568 Blue Mary开公司


    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1568

    题意:两个操作:(1)添加一条直线y=kx+b;(1<=k<=100)(2)询问当前所有直线中x=t时y最大的y是多少?(1<=t<=50000)

    思路:很明显,要把所有的直线维护成凸性,也就是对于任意一个x值,我们只保存y最大的那条直线。那么这个东西要能添加和删除。我们用set,set里按照斜率来建立。对于待插入的的一条直线我们首先找到与其斜率最近的两个,不妨令比其小的为pre,令比其大的为next,那么首先我们要判断要不要插入这条直线,设当前直线为cur,C(i,j)表示i与j的交点。首先我们看若cur与next的斜率相等的话,我们只需要根据其截距来判断要不要插入,若cur的截距小于等于next的截距则无需插入。接下来我们看斜率不等时。我们发现,若C(pre,cur)在next的下方,则无需插入;否则需要插入。那么一旦插入,我们就是要进行更新。比如,对于后继next以及后继的后继next1,若C(cur,next1)在next的上方,则需要将next删除。pre的删除类似。然后我们就能计算出cur在哪些区域上是最优的,[Xl,Xr],然后将该区域上标记为cur最优,这个可以用线段树。
     
    struct node
    {
        double k,b;
     
        node(){}
        node(double _k,double _b)
        {
            k=_k;
            b=_b;
        }
        void get()
        {
            RD(b,k);
        }
     
        bool operator<(const node &b)const
        {
            return k<b.k;
        }
    };
     
     
    node b[N];
     
    struct Node
    {
        int L,R,x;
    };
     
    int n;
    set<node> s;
    #define type set<node>::iterator
     
    Node a[N<<2];
     
     
     
    void pushDown(int t)
    {
        if(a[t].L==a[t].R) return;
        if(a[t].x)
        {
            a[t*2].x=a[t*2+1].x=a[t].x;
            a[t].x=0;
        }
    }
     
     
    void build(int t,int L,int R)
    {
        a[t].L=L;
        a[t].R=R;
        a[t].x=0;
        if(L==R) return;
        int mid=(L+R)>>1;
        build(t*2,L,mid);
        build(t*2+1,mid+1,R);
    }
     
     
    void update(int t,int L,int R,int x)
    {
        if(a[t].L==L&&a[t].R==R)
        {
            a[t].x=x;
            return;
        }
        pushDown(t);
        int mid=(a[t].L+a[t].R)>>1;
        if(R<=mid) update(t*2,L,R,x);
        else if(L>mid) update(t*2+1,L,R,x);
        else
        {
            update(t*2,L,mid,x);
            update(t*2+1,mid+1,R,x);
        }
    }
     
     
     
    int get(int t,int pos)
    {
        if(a[t].x||a[t].L==a[t].R) return a[t].x;
        pushDown(t);
        int mid=(a[t].L+a[t].R)>>1;
        if(pos<=mid) return get(t*2,pos);
        else return get(t*2+1,pos);
    }
     
    double cal(node a,node b)
    {
        return (a.b-b.b)/(b.k-a.k);
    }
     
    void insert(node now)
    {
        now.b-=now.k;
        type s2=s.lower_bound(now),s1=s2;
        s1--;
        node pre=*s1,sub=*s2;
        double x;
        if(now.k==sub.k)
        {
            if(now.b<=sub.b) return;
            s.erase(s2);
            s.insert(now);
        }
        else
        {
            x=(now.b-pre.b)/(pre.k-now.k);
            if(sub.k*x+sub.b>now.k*x+now.b) return;
            s.insert(now);
        }
        s2=s.find(now);s2--;
        while(s2!=s.begin())
        {
            s1=s2; s1--;
            pre=*s1,sub=*s2;
            x=cal(now,pre);
            if(sub.k*x+sub.b>now.k*x+now.b) break;
            s.erase(s2);
            s2=s.find(now);s2--;
        }
        s1=s.find(now);s1++; s2=s1;s2++;
        while(s2!=s.end())
        {
            pre=*s1,sub=*s2;
            x=cal(now,sub);
            if(pre.k*x+pre.b>now.k*x+now.b) break;
            s.erase(s1);
            s1=s.find(now);s1++; s2=s1;s2++;
        }
        b[n]=now;
        s1=s2=s.find(now);s1--;s2++;
        pre=*s1;sub=*s2;
        double x1=cal(now,pre),x2=cal(now,sub);
        int L=(int)ceil(x1),R=(int)floor(x2);
        if(L<1) L=1;
        if(R>50000) R=50000;
        if(L<=R) update(1,L,R,n);
    }
     
    int main()
    {
        s.insert(node(0,0));
        s.insert(node(101,-INF));
        build(1,1,50000);
        int x,k;
        char op[10];
        node now;
        RD(n);
        while(n--)
        {
            RD(op);
            if(op[0]=='P') now.get(),insert(now);
            else
            {
                RD(x); k=get(1,x);
                PR((int)(b[k].k*x+b[k].b)/100);
            }
        }
    }

  • 相关阅读:
    【SPOJ】6779 Can you answer these queries VII
    【SPOJ】1557 Can you answer these queries II
    【SPOJ】2916 Can you answer these queries V
    【CodeForces】86D Powerful array
    【SPOJ】1043 Can you answer these queries I
    【HDU】3727 Jewel
    【HDU】3915 Game
    【SPOJ】1043 Can you answer these queries III
    【SPOJ】2713 Can you answer these queries IV
    成为一名更好的软件工程师的简单方法
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/3460042.html
Copyright © 2020-2023  润新知