李超线段树入门。
#include<iostream>
#include<cstdio>
#include<cmath>
#define R register int
#define ll long long
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=40000,M=100010,X=39989,Y=1e9;
const double eps=1e-8;
int n,id,ans=-1;
double k[M],b[M];
int s[(N+10)<<2];
#define ls (tr<<1)
#define rs (tr<<1|1)
inline int dcmp(const double& x) {
return !fabs(x)<=eps;
}
inline double f(int i,int x) {return k[i]*x+b[i];}
inline bool ck(int i,int j,int x) {
double fi=f(i,x),fj=f(j,x);
return dcmp(fi-fj)?fi<fj:j<i;
}
inline void change(int tr,int l,int r,int LL,int RR,int p) {
if(LL<=l&&r<=RR) {
if(ck(p,s[tr],l)&&ck(p,s[tr],r)) return ;//没有之前的优
if(ck(s[tr],p,l)&&ck(s[tr],p,r)) {
s[tr]=p; return ;//完全比之前的优
}
R md=(l+r)>>1;
if(ck(s[tr],p,md)) swap(s[tr],p);//保证中点最优
if(ck(s[tr],p,l)) change(ls,l,md,LL,RR,p);//向下递归
else change(rs,md+1,r,LL,RR,p);
return ;
} R md=(l+r)>>1;
if(LL<=md) change(ls,l,md,LL,RR,p);
if(RR>md) change(rs,md+1,r,LL,RR,p);
}
inline int query(int tr,int l,int r,int p) {
if(l==r) return s[tr]; R md=(l+r)>>1,t;
return ck(s[tr],t=(p<=md?query(ls,l,md,p):query(rs,md+1,r,p)),p)?t:s[tr];
}
inline void main() {
n=g();
for(R i=1,op,x0,y0,x1,y1;i<=n;++i) {
op=g();
if(op) {
x0=(g()+ans+X)%X+1,y0=((ll)g()+ans+Y)%Y+1,
x1=(g()+ans+X)%X+1,y1=((ll)g()+ans+Y)%Y+1;
++id; if(x0>x1) swap(x0,x1),swap(y0,y1);
if(x0==x1) k[id]=0,b[id]=max(y0,y1);
else k[id]=1.0*(y1-y0)/(x1-x0),b[id]=y0-k[id]*x0;
change(1,1,N,x0,x1,id);
} else {
x0=(g()+ans+X)%X+1;
printf("%d\n",ans=query(1,1,N,x0));
--ans;
}
}
}
} signed main() {Luitaryi::main(); return 0;}
2020.01.16
原文:https://www.cnblogs.com/Jackpei/p/12207572.html