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;
    }
  • 相关阅读:
    jQuery 源码解析(二十四) DOM操作模块 包裹元素 详解
    jQuery 源码解析(二十三) DOM操作模块 替换元素 详解
    jQuery 源码解析(二十二) DOM操作模块 复制元素 详解
    jQuery 源码分析(二十一) DOM操作模块 删除元素 详解
    jQuery 源码分析(二十) DOM操作模块 插入元素 详解
    jQuery 源码分析(十九) DOM遍历模块详解
    python 简单工厂模式
    python 爬虫-协程 采集博客园
    vue 自定义image组件
    微信小程序 image组件坑
  • 原文地址:https://www.cnblogs.com/darlingroot/p/11248951.html
Copyright © 2011-2022 走看看