李超线段树
解决多线段单点最值问题。
浅略的说一下。
每个区间存储位于当前区间中的值最大的线段。每次插入新线段,如果当前区间没有存储线段,就直接插在这里,否则分类讨论一下,如果某一个子区间的最优线段必定是当前线段,这个子区间就不用处理了。而对于另一个有不确定因素的,我们把当前的不优线段下传即可。具体实现看代码,本质上是标记永久化,所以查询的时候直接对于每个点都更新一下答案就好。
#include<bits/stdc++.h>
#define ll long long
#define db double
#define filein(a) freopen(#a".in","r",stdin)
#define fileot(a) freopen(#a".out","w",stdout)
#define Better_IO true
namespace IO{
#if Better_IO
char buf[(1<<20)+3],*p1(buf),*p2(buf);
const int lim=1<<20;
inline char gc(){
if(p1==p2) p2=(p1=buf)+fread(buf,1,lim,stdin);
return p1==p2?EOF:*p1++;
}
#define pc putchar
#else
#define gc getchar
#define pc putchar
#endif
inline bool blank(char c){
return c=='\t' or c=='\n' or c=='\r' or c==' ' or c==EOF;
}
inline void gs(char *s){
char ch=gc();
while(blank(ch) ) ch=gc();
while(!blank(ch) ) {*s++=ch;ch=gc();}
*s=0;
}
inline void ps(char *s){
while(*s!=0) {pc(*s++);}
}
template<class T>
inline void read(T &s){
s=0;char ch=gc();bool f=0;
while(ch<'0'||'9'<ch) {if(ch=='-') f=1;ch=gc();}
while('0'<=ch&&ch<='9') {s=s*10+(ch^48);ch=gc();}
if(ch=='.'){
db p=0.1;ch=gc();
while('0'<=ch&&ch<='9') {s=s+p*(ch^48);ch=gc();p*=0.1;}
}
s=f?-s:s;
}
template<class T,class ...A>
inline void read(T &s,A &...a){
read(s);read(a...);
}
};
using IO::gs;
using IO::ps;
using IO::read;
using IO::gc;
const int N=1e5+3;
int n;
const db inf=1e9;
int tot;
struct line{
db k,b;
}p[N];
inline line change(int sx,int sy,int fx,int fy){
db k,b;
if(sx==fx){
k=0;
b=std::max(sy,fy);
}else{
k=(db)(fy-sy)/(db)(fx-sx);
b=sy-(db)k*sx;
}
return (line){k,b};
}
#define pr std::pair<db,int>
inline pr max(pr x,pr y){
if(x.first<y.first) return y;
else if(x.first>y.first) return x;
return x.second<y.second?x:y;
}
inline db calc(int id,int x){
return (p[id].k*x+p[id].b);
}
const int N2=39989+3;
struct SegTree{
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
struct node{
int l,r,mid;
int id;
}t[N2<<2];
inline void build(int x,int l,int r){
t[x].l=l;t[x].r=r;t[x].mid=(l+r)>>1;
t[x].id=0;
if(l==r){
return;
}
build(lc(x),l,t[x].mid);
build(rc(x),t[x].mid+1,r);
}
inline void modify(int x,int l,int r,int id){
if(t[x].l>r or t[x].r<l) return;
db val1=calc(t[x].id,t[x].mid),val2=calc(id,t[x].mid);
if(l<=t[x].l and t[x].r<=r){
if(!t[x].id){
t[x].id=id;
return;
}
if(t[x].l==t[x].r){
if(val1<val2) t[x].id=id;
else if(val1==val2) t[x].id=std::min(id,t[x].id);
return;
}
if(p[t[x].id].k<p[id].k){
if(val1<val2){
modify(lc(x),l,r,t[x].id);
}else{
modify(rc(x),l,r,id);
}
}else if(p[t[x].id].k>p[id].k){
if(val1<val2){
modify(rc(x),l,r,t[x].id);
}else{
modify(lc(x),l,r,id);
}
}
if(val1<val2) t[x].id=id;
else if(val1==val2) t[x].id=std::min(id,t[x].id);
return;
}
modify(lc(x),l,r,id);
modify(rc(x),l,r,id);
}
inline pr query(int x,int k){
db res=calc(t[x].id,k);
pr ans={res,t[x].id};
if(t[x].l==t[x].r) return ans;
if(k<=t[x].mid) ans=max(ans,query(lc(x),k) );
if(t[x].mid+1<=k) ans=max(ans,query(rc(x),k) );
return ans;
}
#undef lc
#undef rc
}t;
int la;
int main(){
filein(a);fileot(a);
read(n);
p[0]={-1e9,-1e9};
t.build(1,1,39989);
for(int i=1;i<=n;++i){
int op;
read(op);
if(op==0){
int x;
read(x);
x=(x+la-1)%39989+1;
printf("%d\n",la=t.query(1,x).second);
}
if(op==1){
int sx,sy,fx,fy;
read(sx,sy,fx,fy);
sx=(sx+la-1)%39989+1;
sy=(sy+la-1)%(int)1e9+1;
fx=(fx+la-1)%39989+1;
fy=(fy+la-1)%(int)1e9+1;
if(sx>fx){
std::swap(sx,fx);
std::swap(sy,fy);
}
p[++tot]=change(sx,sy,fx,fy);
t.modify(1,sx,fx,tot);
}
}
return 0;
}