zoukankan      html  css  js  c++  java
  • 李超线段树(segment[HEOI2013]-洛谷T4097)

    (neng了好久好久才糊弄懂得知识点...)

    一、李超线段树

        在线动态维护一个二维平面直角坐标系,

        支持插入一条线段,

        询问与直线x = x0相交的所有线段中,交点y的最大/小值

        (若有多条线段符合条件,输出编号最小的线段的编号)

    洛谷板子题-Segment[HEOI2013]-洛谷T4097

    二、add操作

    整个李超线段树的核心就是add操作

    1.特判 l == r

    已经到了一个点

    如果该点之前没有维护线段,直接维护现在的线段

    如果该点已经维护过,选择纵坐标靠上的直线(点),纵坐标相同,选择编号较小的

    2.如果没有恰好放在区间里

    如果不过mid,根据与mid关系左右查找

    如果过mid,劈两半分别查找

    3.如果找到了恰好的区间

    如果该区间没有维护线段,维护该线段

    如果有,

    (1).如果中点处新的有,留下新的,把旧的中,稍大的一般留下(全劣则淘汰),下放到对应的子区间。

    (2).如果中点处值相同。一般情况选择新的劈断的下放(省的建线段)。但是当新的编号较小,并且新的线段的右端点的纵坐标大于等于旧的,将旧的右半部分下放(使mid处一定取得的使新的线段,也就是编号较小的)

    (3).如果中点处旧的优,同理...

    //李超线段树
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    inline int read()
    {
        int sum = 0,p = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-')
                p = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            (sum *= 10) += ch - '0';
            ch = getchar();
        }
        return sum * p;
    }
    
    #define mid ((l + r)>>1)
    #define lson l,mid,o<<1
    #define rson mid + 1,r,o<<1|1
    
    const int mod1 = 39989,mod2 = 1e9,N = 50100;;
    int n,ans,lastans,id;//ans实际答案,lastans上次查询的答案,id给函数编的号 
    int  sx1[N << 2],sx2[N << 2],sy1[N << 2],sy2[N << 2],sum[N << 2];
    bool vis[N << 2];
    double tval;
    
    //求节点储存的原函数的o点的值 
    double G(int o,int x1,int y1,int x2,int y2)
    {
        if(x1 == x2)
            return y2;
        else
            return 1.0 *(o - x2) *(y1 - y2)/(x1 - x2) +y2;
    }
    
    //当新加入的函数是一条垂直于x轴的直线时 的修改操作 
    void change(int x,int v,int tot,int l,int r,int o)
    {
        if(l == r)
        {
            if(!vis[o])
            {
                sx1[o] = sx2[o] = l;
                sy1[o] = sy2[o] = v;
                sum[o] = tot;
                vis[o] = true;
            }
            else
            {
                double cnt = G(x,sx1[o],sy1[o],sx2[o],sy2[o]);
                if(cnt > v || (cnt == v && tot < sum[o]))
                {
                    sx1[o] = sx2[o] = l;
                    sy1[o] = sy2[o] = v;
                    sum[o] = tot;
                }
            }
            return;
        }
        if(mid >= x)
            change(x,v,tot,lson);
        else
            change(x,v,tot,rson);
    }
    
    //求两个函数的交点 
    double Inter(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4)
    {
        double a,b,c,d,g,h,f,t,s;
        a = x2 - x1;
        b = x3 - x4;
        c = y2 - y1;
        d = y3 - y4;
        g = x3 - x1;
        h = y3 - y1;
        f = a *d - b * c;
        t = (d * g - b * h)/f;
        return x1 +t * (x2 - x1);
    }
    
    void update(int ql,int qr,int x1,int y1,int x2,int y2,int tot,int l,int r,int o)
    {
        if(ql <= l && r <= qr)
        {
            if(!vis[o])
            {
                sx1[o] = x1,sy1[o] = y1,sx2[o] = x2,sy2[o] = y2;
                sum[o] = tot;
                vis[o] = true;
            }
            else
            {
                double f1,f2,f3,f4;
                f1 = G(l,x1,y1,x2,y2);
                f2 = G(l,sx1[o],sy1[o],sx2[o],sy2[o]);
                f3 = G(r,x1,y1,x2,y2);
                f4 = G(r,sx1[o],sy1[o],sx2[o],sy2[o]);
                if(f1 <= f2 && f3 <= f4)
                    return;
                else if(f1 >= f2 && f3 >= f4)
                {
                    sx1[o] = x1,sy1[o] = y1,sx2[o] = x2,sy2[o] = y2;
                    sum[o] = tot;
                }
                else
                {
                    double spot = Inter(x1,y1,x2,y2,sx1[o],sy1[o],sx2[o],sy2[o]);
                    if(f1 >= f2)
                    {
                        if(spot <= mid)
                            update(ql,qr,x1,y1,x2,y2,tot,lson);
                        else
                        {
                            update(ql,qr,sx1[o],sy1[o],sx2[o],sy2[o],sum[o],rson);
                            sx1[o] = x1,sy1[o] = y1,sx2[o] = x2,sy2[o] = y2;
                            sum[o] = tot;
                        }
                    }
                    else
                    {
                        if(spot > mid)
                            update(ql,qr,x1,y1,x2,y2,tot,rson);
                        else
                        {
                            update(ql,qr,sx1[o],sy1[o],sx2[o],sy2[o],sum[o],lson);
                            sx1[o] = x1,sy1[o] = y1,sx2[o] = x2,sy2[o] = y2;
                            sum[o] = tot;
                        }
                    }
                }
            }
            return;
        }
        if(ql <= mid)
            update(ql,qr,x1,y1,x2,y2,tot,lson);
        if(qr > mid)
            update(ql,qr,x1,y1,x2,y2,tot,rson);
    }
    
    void query(int x,int l,int r,int o)
    {
        if(vis[o])
        {
            double cnt = G(x,sx1[o],sy1[o],sx2[o],sy2[o]);
            if(cnt > tval || cnt == tval && sum[o] < ans)
            {
                tval = cnt;
                ans = sum[o];
            }
        }
        if(l == r)
            return;
        if(mid >= x)
            query(x,lson);
        else
            query(x,rson);
    }
    
    int main()
    {
        n = read();
        while(n--)
        {
            int opt = read();
            if(!opt)
            {
                int x = read();
                x = (x + lastans - 1)%mod1 + 1;
                ans = 0;
                tval = 0;
                query(x,1,50000,1);
                printf("%d
    ",ans);
                lastans = ans;
            }
            else
            {
                int x1 = read(),y1 = read(),x2 = read(),y2 = read();
                x1 = (x1 + lastans - 1)%mod1 + 1;
                y1 = (y1 + lastans - 1)%mod2 + 1;
                x2 = (x2 + lastans - 1)%mod1 + 1;
                y2 = (y2 + lastans - 1)%mod2 + 1;
                if(x1 > x2)
                {
                    swap(x1,x2);
                    swap(y1,y2);
                }
                if(x1 == x2)
                    change(x1,max(y1,y2),++id,1,50000,1);
                else
                    update(x1,x2,x1,y1,x2,y2,++id,1,50000,1);
            }
        }
        return 0;
    }
  • 相关阅读:
    (10)进程---Manager数据共享
    (9)进程---JoinableQueue队列
    (8)进程---Queue队列
    (7)Pool进程池
    (6)进程---Event事件
    (5)进程--锁和信号量
    (4)进程---daemon守护进程和join阻塞
    XSLT知识点【一】
    XSL-FO知识点【一】
    XPath知识点【一】
  • 原文地址:https://www.cnblogs.com/darlingroot/p/11248951.html
Copyright © 2011-2022 走看看