码迷,mamicode.com
首页 > 其他好文 > 详细

李超线段树

时间:2019-06-24 22:47:29      阅读:141      评论:0      收藏:0      [点我收藏+]

标签:logs   ble   坐标   upd   递归   线段树   博客   怎么   color   

李超线段树:动态维护一个平面直角坐标系,支持在中间插入一条线段(或直线),询问与x=x0这条直线相交的所有线段中,交点的y坐标的最大(小)值。

线段树上每个区间维护在mid处y坐标最大的线段。(要标记永久化)

考虑怎么插入一条直线,假设它当前处理到了某个区间:(摘自yyb的博客https://www.cnblogs.com/cjyyb/p/10560973.html

  • 如果这个区间没有记录最长的线段,那么直接把这个区间记录的线段修改为这条线段,然后返回。
  • 如果当前线段在这个区间内已经被这个区间记录的线段覆盖,那么直接gg,返回就好了。
  • 反过来,如果完全覆盖了之前记录的线段,那么直接赋值、返回。
  • 否则和已经记录的直线有交,判断哪根线段覆盖的区域较长,把这个区间记录的值给修改一下,然后把短的那一半丢下去递归。
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=100005;
    int n,i;
    bool v[N*5];
    double x,y,K[N*5],B[N*5];
    char ch[20];
    void update(int o,int l,int r,double k,double b)
    {
        if(!v[o])
        {v[o]=true,K[o]=k,B[o]=b;return;}
        if(l==r)
        {
            if(k*l+b>K[o]*l+B[o])
                K[o]=k,B[o]=b;
            return;
        }
        int mid=l+r>>1;
        double l1=k*l+b,r1=k*r+b,l2=K[o]*l+B[o],r2=K[o]*r+B[o];
        if(l1>=l2&&r1>=r2)
        {K[o]=k,B[o]=b;return;}
        if(l1<=l2&&r1<=r2)
            return;
        double x=(b-B[o])/(K[o]-k);
        if(l1>=l2)
        {
            if(x>mid)
            {update(o<<1|1,mid+1,r,K[o],B[o]);K[o]=k,B[o]=b;}
            else
                update(o<<1,l,mid,k,b);
        }
        else
        {
            if(x>mid)
                update(o<<1|1,mid+1,r,k,b);
            else
            {update(o<<1,l,mid,K[o],B[o]);K[o]=k,B[o]=b;}
        }
    }
    double query(int o,int l,int r,int x)
    {
        if(l==r)
            return K[o]*l+B[o];
        int mid=l+r>>1;
        double rtn=(v[o]?K[o]*x+B[o]:0.0);
        if(x<=mid)
            return max(rtn,query(o<<1,l,mid,x));
        else
            return max(rtn,query(o<<1|1,mid+1,r,x));
    }
    int main()
    {
        freopen("company.in","r",stdin);
        freopen("company.out","w",stdout);
        scanf("%d",&n);
        while(n--)
        {
            scanf("%s",ch);
            if(ch[0]==P)
            {
                scanf("%lf%lf",&x,&y);
                update(1,1,50000,y,x-y);
            }
            else
            {
                scanf("%d",&i);
                printf("%d\n",max(0,(int)query(1,1,50000,i)/100));
            }
        }
        return 0;
    }

     

李超线段树

标签:logs   ble   坐标   upd   递归   线段树   博客   怎么   color   

原文地址:https://www.cnblogs.com/pthws/p/11079795.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!