[HEOI2013]Segment

https://www.luogu.org/problemnew/show/P4097

李超线段树模板题。

插入一条线段,用log(n)的复杂度将它分配到不同区间内,对于每个区间,又要用log(n)的复杂度判断在所有子区间的优劣程度。

所以,插入复杂度是log^2(n)的,查询复杂度依然为log(n)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=100005,md1=39989,md2=1000000000;
struct node
{
    int l,r;
    double k,b;
}p[N];
int n,i,len,ans,X0,Y0,X1,Y1,w[N*5],g[N];
double e;
void update(int o,int l,int r,int id)
{
    int mid=l+r>>1;
    if(l>=p[id].l&&r<=p[id].r)
    {
        if(!w[o])
        {w[o]=id;return;}
        double l1=p[id].k*l+p[id].b,r1=p[id].k*r+p[id].b;
        double l2=p[w[o]].k*l+p[w[o]].b,r2=p[w[o]].k*r+p[w[o]].b;
        if(l1>l2&&r1>r2)
        {w[o]=id;return;}
        if(l1<=l2&&r1<=r2)
            return;
        double x=(p[id].b-p[w[o]].b)/(p[w[o]].k-p[id].k);
        if(l1>=l2)
        {
            if(x>mid)
            {update(o<<1|1,mid+1,r,w[o]);w[o]=id;}
            else
                update(o<<1,l,mid,id);
        }
        else
        {
            if(x<=mid)
            {update(o<<1,l,mid,w[o]);w[o]=id;}
            else
                update(o<<1|1,mid+1,r,id);
        }
        return;
    }
    if(p[id].l<=mid)
        update(o<<1,l,mid,id);
    if(p[id].r>mid)
        update(o<<1|1,mid+1,r,id);
}
void query(int o,int l,int r,int x)
{
    if(w[o])
    {
        if(p[w[o]].k*x+p[w[o]].b>e||(p[w[o]].k*x+p[w[o]].b==e&&w[o]<ans))
            ans=w[o],e=p[w[o]].k*x+p[w[o]].b;
    }
    if(l==r)
        return;
    int mid=l+r>>1;
    if(x<=mid)
        query(o<<1,l,mid,x);
    else
        query(o<<1|1,mid+1,r,x);
}
int main()
{
    freopen("segment.in","r",stdin);
    freopen("segment.out","w",stdout);
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&i);
        if(i==1)
        {
            ++len;
            scanf("%d%d%d%d",&X0,&Y0,&X1,&Y1);
            X0=(X0+ans-1)%md1+1,Y0=(Y0+ans-1)%md2+1;
            X1=(X1+ans-1)%md1+1,Y1=(Y1+ans-1)%md2+1;
            if(X0>X1)
                swap(X0,X1),swap(Y0,Y1);
            if(X0!=X1)
            {
                p[len]=(node){X0,X1,1.0*(Y1-Y0)/(X1-X0),Y0-1.0*(Y1-Y0)/(X1-X0)*X0};
                update(1,1,md1,len);
            }
            else
            {
                p[len].r=Y1;
                if(Y1>p[g[X0]].r)
                    g[X0]=len;
            }
        }
        else
        {
            scanf("%d",&X0);
            X0=(X0+ans-1)%md1+1;
            ans=g[X0];e=p[g[X0]].r;
            query(1,1,md1,X0);
            printf("%d\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/pthws/p/11080152.html