change
在x坐标区间[l,r]
上新增编号为id的线段(x坐标范围为[L,R]
),更新最大y值
query
查询x坐标区间[l,r]上的最大
#define N 50005
#define ls u<<1
#define rs u<<1|1
int n,cnt;
struct line{
double k,b; //斜率,截距
}p[N*2];
int tr[N*4]; //线段编号
double Y(int id,int x){ //求Y值
return p[id].k*x+p[id].b;
}
void change(int u,int l,int r,int L,int R,int id){ //修改
int mid=(l+r)>>1;
if(L<=l&&r<=R){
if(Y(id,mid)>Y(tr[u],mid)) swap(id,tr[u]);
if(Y(id,l)>Y(tr[u],l)) change(ls,l,mid,L,R,id);
if(Y(id,r)>Y(tr[u],r)) change(rs,mid+1,r,L,R,id);
return;
}
if(L<=mid) change(ls,l,mid,L,R,id);
if(mid<R) change(rs,mid+1,r,L,R,id);
}
double query(int u,int l,int r,int x){ //查询
if(l==r) return Y(tr[u],x);
int mid=(l+r)>>1;
double t=Y(tr[u],x);
if(x<=mid) return max(t,query(ls,l,mid,x));
else return max(t,query(rs,mid+1,r,x));
}
如果插入的是直线,认为线段范围包含了整个区间,条件L<=l&&r<=R
必定成立。
维护所有直线的上凸壳
using ll = long long;
#define N 100005
#define ls u<<1
#define rs u<<1|1
struct line{
ll k,b; //斜率,截距
} p[N*2];
int tr[N*4]; //线段编号
int cnt = 0;
ll Y(int id,int x){ //求Y值
return p[id].k*x+p[id].b;
}
void change(int u,int l,int r,int id){ //修改
int mid=(l+r)>>1;
if(Y(id,mid)>Y(tr[u],mid)) swap(id,tr[u]);
if(Y(id,l)>Y(tr[u],l)) change(ls,l,mid,id);
if(Y(id,r)>Y(tr[u],r)) change(rs,mid+1,r,id);
}
ll query(int u,int l,int r,int x){ //查询
if(l==r) return Y(tr[u],x);
int mid=(l+r)>>1;
ll t=Y(tr[u],x);
if(x<=mid) return max(t,query(ls,l,mid,x));
else return max(t,query(rs,mid+1,r,x));
}
void addline(ll k, ll b) {
p[++cnt] = {k, b};
change(1, 0, N, cnt);
}