[学习笔记/做题记录]李超树

李超树实际上就是每个处理其区间内在凸包上出现最大部分的那条线段。
然后单点查询时,其答案一定在其到根节点上的某个节点上的答案线段上。

加入线段:

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;
		}
	}
} 
原文地址:https://www.cnblogs.com/dixiao/p/15673974.html