李超树实际上就是每个处理其区间内在凸包上出现最大部分的那条线段。
然后单点查询时,其答案一定在其到根节点上的某个节点上的答案线段上。
加入线段:
inline void upd(int u,int l,int r,int x){
if(s[t[u]].val(mid) < s[x].val(mid))std::swap(x,t[u]);
if(s[t[u]].val(l) < s[x].val(l))upd(ls(u),l,mid,x);
if(s[t[u]].val(r) < s[x].val(r))upd(rs(u),mid + 1,r,x);
}
inline void ins(int u,int l,int r,int tl,int tr,int v){
if(tl <= l && r <= tr){
upd(u,l,r,v);
return ;
}
if(tl <= mid)
ins(ls(u),l,mid,tl,tr,v);
if(tr > mid)
ins(rs(u),mid + 1,r,tl,tr,v);
}
单点查询:
inline int qry(int k,int l,int r,int x){
if(l > x || r < x)return 0;
if(l == x && r == x)return t[k];
return M(M(qry(ls(k),l,mid,x),qry(rs(k),mid + 1,r,x),x),t[k],x);
}
[HEOI2013]Segment
板子题。
[HEOI2013]Segment
#define ll long long
#define N 100010
#define lim 40000
#define int long long
int n;
#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
#define mid ((l + r) >> 1)
int las;
struct P{
double k,b;
void get(ll a,ll B,ll c,ll d){k = (a == c ? 0 : 1.0 * (B - d) / (a - c));b = B - a * k;}
double val(int x){return k * x + b;}
}s[N];
int t[N << 2];
inline void upd(int u,int l,int r,int x){
if(s[t[u]].val(mid) < s[x].val(mid))std::swap(x,t[u]);
if(s[t[u]].val(l) < s[x].val(l))upd(ls(u),l,mid,x);
if(s[t[u]].val(r) < s[x].val(r))upd(rs(u),mid + 1,r,x);
}
inline void ins(int u,int l,int r,int tl,int tr,int v){
if(tl <= l && r <= tr){
upd(u,l,r,v);
return ;
}
if(tl <= mid)
ins(ls(u),l,mid,tl,tr,v);
if(tr > mid)
ins(rs(u),mid + 1,r,tl,tr,v);
}
inline int M(int a,int b,int x){
double s1 = s[a].val(x),s2 = s[b].val(x);
return (s1 == s2) ? std::min(a,b) : (s1 > s2 ? a : b);
}
inline int qry(int k,int l,int r,int x){
if(l > x || r < x)return 0;
if(l == x && r == x)return t[k];
return M(M(qry(ls(k),l,mid,x),qry(rs(k),mid + 1,r,x),x),t[k],x);
}
inline void cha(ll &x,int v = 1){x = (x + las - 1) % (v ? 39989:1000000000)+1;}
int cnt;
signed main(){
scanf("%lld",&n);
while(n -- ){
int op;
scanf("%d",&op);
if(op){
ll a,b,c,d;
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
cha(a),cha(b,0),cha(c),cha(d,0);
if(a > c)std::swap(a,c),std::swap(b,d);
s[++cnt].get(a,b,c,d),ins(1,1,lim,a,c,cnt);
} else{
ll x;
scanf("%lld",&x);
cha(x);
std::cout<<(las = qry(1,1,lim,x))<<std::endl;
}
}
}