题意:有 n n n次操作,每次操作可能有两种,第一种是插入一条线段,告诉你线段的两个端点,其中 1 < = x < = 39990 1<=x<=39990 1<=x<=39990, 1 < = y < = 1 e 9 1<=y<=1e9 1<=y<=1e9,保证端点都是整数。第二种操作是询问与 x = k x=k x=k这条直线相交的所有线段的 k k k这个横坐标下的纵坐标的最大值。强制在线。 n < = 1 e 5 n<=1e5 n<=1e5。如果有多个线段,输出编号最小的。
题解:
李超树模板题。注意题目中可能存在线段是一个点的情况,也就是两个端点
x
x
x相同,这样要求取最大的那个
y
y
y。其他的没什么好说的。只要会李超树就知道该怎么做,不会的看我这篇博客。
代码:
#include <bits/stdc++.h>
using namespace std;
int n,ans,cnt;
double eps=1e-8;
struct line
{
double k,b;
}li[100010];
struct node
{
int l,r,id;
}tr[400010];
inline void build(int rt,int l,int r)
{
tr[rt].l=l;
tr[rt].r=r;
tr[rt].id=0;
if(l==r)
return;
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
inline double calc(int id,int x)
{
return li[id].k*x+li[id].b;
}
inline void update(int rt,int le,int ri,int id)
{
int l=tr[rt].l,r=tr[rt].r;
if(le<=l&&r<=ri)
{
int mid=(l+r)>>1;
if(calc(id,l)>=calc(tr[rt].id,l)+eps&&calc(id,r)>=calc(tr[rt].id,r)+eps)
tr[rt].id=id;
else if(calc(id,l)>=calc(tr[rt].id,l)+eps)
{
if(calc(id,mid)>=calc(tr[rt].id,mid)+eps)
{
update(rt<<1|1,le,ri,tr[rt].id);
tr[rt].id=id;
}
else
update(rt<<1,le,ri,id);
}
else if(calc(id,r)>=calc(tr[rt].id,r)+eps)
{
if(calc(id,mid)>=calc(tr[rt].id,mid)+eps)
{
update(rt<<1,le,ri,tr[rt].id);
tr[rt].id=id;
}
else
update(rt<<1|1,le,ri,id);
}
return;
}
int mid=(l+r)>>1;
if(le<=mid)
update(rt<<1,le,ri,id);
if(mid+1<=ri)
update(rt<<1|1,le,ri,id);
}
inline int query(int rt,int x)
{
int l=tr[rt].l,r=tr[rt].r;
if(l==r)
return tr[rt].id;
int mid=(l+r)>>1;
int res=0;
if(x<=mid)
res=query(rt<<1,x);
else
res=query(rt<<1|1,x);
if(res==0)
return tr[rt].id;
else if(li[res].k*x+li[res].b>li[tr[rt].id].k*x+li[tr[rt].id].b+eps)
return res;
else if(fabs(calc(res,x)-calc(tr[rt].id,x))<=eps&&res<tr[rt].id)
return res;
else
return tr[rt].id;
}
int main()
{
build(1,1,50000);
li[0].k=-2.0;
li[0].b=-1000000000.0;
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
int opt,a,b,c,d;
scanf("%d",&opt);
if(opt==0)
{
scanf("%d",&a);
a=(a+ans-1)%39989+1;
ans=query(1,a);
printf("%d\n",ans);
}
else
{
scanf("%d%d%d%d",&a,&b,&c,&d);
a=(a+ans-1)%39989+1;
b=(b+ans-1)%1000000000+1;
c=(c+ans-1)%39989+1;
d=(d+ans-1)%1000000000+1;
if(a==c)
{
li[++cnt].k=0;
li[cnt].b=max(b,d);
}
else
{
li[++cnt].k=1.0*(d-b)/(1.0*(c-a));
li[cnt].b=1.0*b-li[cnt].k*a;
}
update(1,min(a,c),max(a,c),cnt);
}
}
return 0;
}