李超线段树[模板]

#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10,M=39989;
const double eps=1e-9;
int lasans,cnt,n,sh[N];
struct stu
{
    double k,b;
}q[N];
struct node
{
    double zhi;int id;
};
double calc(int x,int wz){return q[x].b+q[x].k*wz;}
int cmp(double zhix,double zhik)
{
    if(zhix-zhik>eps)return 1;
    if(zhik-zhix>eps)return 2;//注意用正的去比较
    return 0;
}
void upd(int x,int l,int r,int k)
{
    int mid=(l+r)>>1;
    int fmid=cmp(calc(sh[x],mid),calc(k,mid));//比较sh[x]和k在mid处的值,顺序
    if(fmid==2||(fmid==0&&sh[x]>k))swap(sh[x],k);//保证在中点sh[x]>=k
    int fl=cmp(calc(sh[x],l),calc(k,l)),fr=cmp(calc(sh[x],r),calc(k,r));
    if(fl==2||(fl==0&&sh[x]>k))upd(x<<1,l,mid,k);//左端点高,更新左子树
    if(fr==2||(fr==0&&sh[x]>k))upd(x<<1|1,mid+1,r,k);
    return ;
}
void update(int x,int l,int r,int lt,int rt,int k)
{
    if(l>=lt&&r<=rt)
    {
        upd(x,l,r,k);//找被完整覆盖的区间,更新值
        return;
    }
    int mid=(l+r)>>1;
    if(lt<=mid)update(x<<1,l,mid,lt,rt,k);
    if(rt>mid)update(x<<1|1,mid+1,r,lt,rt,k);
}
void add(int x0,int y0,int x1,int y1)
{
    if(x0==x1){q[++cnt].k=0;q[cnt].b=max(y0,y1);}//处理与y轴平行的线段
    else{q[++cnt].k=1.0*(y1-y0)/(x1-x0);q[cnt].b=y0-q[cnt].k*x0;}
}
node nmax(node x,node y)
{
    int f=cmp(x.zhi,y.zhi);
    if(f==1)return x;
    if(f==2)return y;
    else return x.id<y.id?x:y;
}
node query(int x,int l,int r,int k)
{
    if(r<k||l>k)return {0,0};//不在区间内
    int mid=(l+r)>>1;
    double zhi=calc(sh[x],k);
    if(l==r)return {zhi,sh[x]};
    return nmax({zhi,sh[x]},nmax(query(x<<1,l,mid,k),query(x<<1|1,mid+1,r,k)));
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int op;
        cin>>op;
        if(op==1)
        {
            int x0,y0,x1,y1;
            cin>>x0>>y0>>x1>>y1;
            x0=(x0+lasans-1)%39989+1;x1=(x1+lasans-1)%39989+1;
            y0=(y0+lasans-1)%1000000000+1;y1=(y1+lasans-1)%1000000000+1;//强制在线
            if(x0>x1)swap(x0,x1),swap(y0,y1);//保证左右端点
            add(x0,y0,x1,y1);//增加一个线段。
            update(1,1,M,x0,x1,cnt);
        }
        else
        {
            int x;cin>>x;
            x=(x+lasans-1)%39989+1;
            cout<<(lasans=query(1,1,M,x).id)<<'\n';
        }
    }
	return 0;
} 

1.要加一个哨兵,防止有的边加不进去。

posted @   storms11  阅读(6)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示