3165: [Heoi2013]Segment
李超线段树板子题。
对一次函数进行分治处理。
#include<cstdio>
#include<algorithm>
#define EXP 1e-8
#define N9 1000000000
using namespace std;
const int MAXN=100005;
struct Seg{
double K,B;int id;
double f(int x){return K*x+B;}
};
int n,Ans;
#include<cctype>
int read(){
int ret=0;char ch=getchar();bool f=1;
for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');
for(; isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;
return f?ret:-ret;
}
struct LC_Tree{
Seg Tre[MAXN<<2];bool vis[MAXN<<2];
void PushDown(int rt,int L,int R,Seg p){
if(!vis[rt]) return (void)(vis[rt]=1,Tre[rt]=p);
double L1=p.f(L),R1=p.f(R),L2=Tre[rt].f(L),R2=Tre[rt].f(R);
if(L2>=L1&&R2>=R1) return;
if(L2<=L1&&R2<=R1) return (void)(Tre[rt]=p);
double pos=(p.B-Tre[rt].B)/(Tre[rt].K-p.K);
int mid=(R+L)>>1;
if(pos<=mid) PushDown(rt<<1,L,mid,R1>R2?Tre[rt]:p);
else PushDown(rt<<1|1,mid+1,R,L1>L2?Tre[rt]:p);
if((L1>L2&&pos>=mid)||(R1>R2&&pos<mid)) Tre[rt]=p;
}
void Insert(int rt,int L,int R,int l,int r,Seg p){
if(l<=L&&R<=r) return (void)(PushDown(rt,L,R,p));
int mid=(R+L)>>1;
if(l<=mid) Insert(rt<<1,L,mid,l,r,p);
if(r>mid) Insert(rt<<1|1,mid+1,R,l,r,p);
}
double _abs(double x){return x<0?-x:x;}
Seg Query(int rt,int L,int R,int p){
if(L==R) return vis[rt]?Tre[rt]:(Seg){0,0,0};
int mid=(L+R)>>1;Seg now=(Seg){0,0,0};
if(p<=mid) now=Query(rt<<1,L,mid,p);
else now=Query(rt<<1|1,mid+1,R,p);
if(!vis[rt]) return now;
double p1=Tre[rt].f(p),p2=now.f(p);
if(!now.id||p1>p2||(_abs(p1-p2)<EXP&&Tre[rt].id<now.id)) return Tre[rt];
else return now;
}
}T;
int main(){
n=read();
for(int i=1,tot=0;i<=n;i++){
int Type=read();
if(Type){
int x=(read()+Ans-1)%39989+1,y=(read()+Ans-1)%N9+1,_x=(read()+Ans-1)%39989+1,_y=(read()+Ans-1)%N9+1;
if(x>_x) swap(x,_x),swap(y,_y);
if(x==_x) T.Insert(1,1,39989,x,_x,(Seg){0.0,max(y,_y),++tot});
else{
double k=1.0*(1.0*y-_y)/(x-_x),b=1.0*y-k*x;
T.Insert(1,1,39989,x,_x,(Seg){k,b,++tot});
}
}else{
int x=(read()+Ans-1)%39989+1;
printf("%d\n",Ans=T.Query(1,1,39989,x).id);
}
}
return 0;
}