总结-李超线段树

概念

李超线段树可用来维护直线关系,支持:

  • 加入一条直线
  • 询问单点对应最优直线

结构与普通线段树类似,但更多分情况讨论

LuoguP4254 [JSOI2008]Blue Mary开公司

模板

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); (a) <= (c); ++(a))
#define nR(a,b,c) for(register int a = (b); (a) >= (c); --(a))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ll long long
#define u32 unsigned int
#define u64 unsigned long long
 
#define ON_DEBUGG
 
#ifdef ON_DEBUGG
 
#define D_e_Line printf("\n----------\n")
#define D_e(x) cout << (#x) << " : " << x << endl
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#include <ctime>
#define TIME() fprintf(stderr, "\ntime: %.3fms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else
 
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
//char buf[1 << 21], *p1 = buf, *p2 = buf;
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
 
#endif
 
using namespace std;
struct ios{
    template<typename ATP>inline ios& operator >> (ATP &x){
        x = 0; int f = 1; char ch;
        for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
        while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
        x *= f;
        return *this;
    }
}io;
 
template<typename ATP>inline ATP Max(ATP a, ATP b){
    return a > b ? a : b;
}
template<typename ATP>inline ATP Min(ATP a, ATP b){
    return a < b ? a : b;
}
template<typename ATP>inline ATP Abs(ATP a){
    return a < 0 ? -a : a;
}

const int N = 5e5 + 7;
const int M = 5e5 + 3;

int tot;

double K[N << 1], B[N << 1];

int t[N << 2] ;
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
// y = k * x + b

double Calc(int id, int x) {
	return K[id] * (x - 1) + B[id];
}

inline void Updata(int rt, int l, int r, int x) {
	if(l == r){
		if(Calc(x, l) > Calc(t[rt], l)) t[rt] = x;
		return;
	}
	int mid = (l + r) >> 1;
	if(K[t[rt]] < K[x]){
		if(Calc(x, mid) > Calc(t[rt], mid)){
			Updata(lson, t[rt]);
			t[rt] = x;
		}
		else{
			Updata(rson, x);
		}
	}
	if(K[t[rt]] > K[x]){
		if(Calc(x, mid) > Calc(t[rt], mid)){
			Updata(rson, t[rt]);
			t[rt] = x;
		}
		else{
			Updata(lson, x);
		}
	}
}

inline double Query(int rt, int l, int r, int x) {
	if(l == r) return Calc(t[rt], x);
	int mid = (l + r) >> 1;
	if(x <= mid){
		return Max(Calc(t[rt],x), Query(lson, x));
	}
	else{
		return Max(Calc(t[rt], x), Query(rson, x));
	}

}
int main() {
	int n;
	io >> n;
	char opt[13];
	while(n--){
		scanf("%s", opt + 1);
		if(opt[1] == 'P'){
			++tot;
			scanf("%lf%lf", &B[tot], &K[tot]);
			Updata(1, 1, M, tot);
		}
		else{
			int x;
			io >> x;
			printf("%d\n", (int)Query(1, 1, M, x) / 100);
		}
	}
	
	return 0;
}

LuoguP4069 [SDOI2016]游戏

树链剖分后李超树维护

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); a <= (c); ++a)
#define nR(a,b,c) for(register int a = (b); a >= (c); --a)
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))

#define ON_DEBUGG

#ifdef ON_DEBUGG

#define D_e_Line printf("\n-----------\n")
#define D_e(x) std::cerr << (#x) << " : " <<x << "\n"
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#define Pause() system("pause")
#include <ctime>
#define TIME() fprintf(stderr, "\nTIME : %.3lfms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else

#define D_e_Line ;
#define D_e(x) ;
#define FileOpen() ;
#define FilSave ;
#define Pause() ;
#define TIME() ;

#endif

struct ios {
	template<typename ATP> ios& operator >> (ATP &x) {
		x = 0; int f = 1; char c;
		for(c = getchar(); c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
		while(c >= '0' && c <= '9') x = x * 10 + (c ^ '0'), c = getchar();
		x *= f;
		return *this;
	}
}io;

using namespace std;

template<typename ATP> inline ATP Min(ATP a, ATP b) {
	return a < b ? a : b;
}
template<typename ATP> inline ATP Max(ATP a, ATP b) {
	return a > b ? a : b;
}

const int N = 200007;

#define int long long

int n;

struct Edge {
	int nxt, pre, w;
}e[N << 1];
int head[N], cntEdge;
inline void add(int u, int v, int w) {
	e[++cntEdge] = (Edge){ head[u], v, w}, head[u] = cntEdge;
}

int dis[N], rnk[N]; // be careful

struct Line {
	int K, B, val;
	Line(int K = 0, int B = 123456789123456789ll, int val = 123456789123456789ll) : K(K), B(B), val(val) {}
	inline int Calc(int x) {
		return K * x + B;
	}
}t[N << 2];

namespace ST {
	int dis[N << 2], mn[N << 2];
	
	#define ls rt << 1
	#define rs rt << 1 | 1
	#define lson rt << 1, l, mid
	#define rson rt << 1 | 1, mid + 1,r
	
	inline void Pushup(int &rt) {
		mn[rt] = Min(mn[rt], Min(mn[ls], mn[rs]));
	}
	
	inline void Updata(int rt, int l, int r, Line x) {
        int mid = (l + r) >> 1;
        x.val = x.Calc(dis[mid]);
        if(x.val < t[rt].val){
        	mn[rt] = Min(mn[rt], Min(x.Calc(dis[l]), x.Calc(dis[r])));
        	swap(x, t[rt]);
		}
		if(l == r) return;
		if(x.Calc(dis[l]) >= t[rt].Calc(dis[l]) && x.Calc(dis[r]) >= t[rt].Calc(dis[r])) return;
		if(x.K > t[rt].K)
			Updata(lson, x);
		else
			Updata(rson, x);
		Pushup(rt);
	}
	
	inline void Updata(int rt, int l, int r, int L, int R, Line x) {
		if(L <= l && r <= R){
			Updata(rt, l, r, x);
			return;
		}
		int mid = (l + r) >> 1;
		if(L <= mid) Updata(lson, L, R, x);
		if(R > mid) Updata(rson, L, R, x);
		Pushup(rt);
	}
	
	inline int Query(int rt, int l, int r, int L, int R) {
		if(L <= l && r <= R) return mn[rt];
		int minn = Min(t[rt].Calc(dis[Max(l, L)]), t[rt].Calc(dis[Min(r, R)]));
		int mid = (l + r) >> 1;
		if(L <= mid) minn = Min(minn, Query(lson, L, R));
		if(R > mid) minn = Min(minn, Query(rson, L, R));
		return minn;
	}
	
	inline void Build(int &n) {
//		if(l == r){
//			ST::dis[rt] = ::dis[::rnk[l]];
//			mn[rt] = 123456789123456789ll;
//			return;
//		}
//		int mid = (l + r) >> 1;
//		Build(lson), Build(rson);
//		Pushup(rt);
		R(i,1,n) ST::dis[i] = ::dis[::rnk[i]];
		nR(i,n << 2,1) mn[i] = 123456789123456789ll;
	}
}

namespace TP {
	int dfn[N], dfnIndex, top[N], fa[N], siz[N], son[N], dep[N];
	
	inline void DFS_First(int u, int father) {
		dep[u] = dep[father] + 1, fa[u] = father, siz[u] = 1;
		for(register int i = head[u];i ; i=  e[i].nxt){
			int v= e[i].pre;
			if(v == father) continue;
			dis[v] = dis[u] + e[i].w;
			DFS_First(v, u);
			siz[u] += siz[v];
			if(siz[v] > siz[son[u]]) son[u] = v;
		}
	}
	
	inline void DFS_Second(int u, int Tp) {
		top[u]= Tp, dfn[u] = ++dfnIndex, rnk[dfnIndex] = u;
		if(!son[u]) return;
		DFS_Second(son[u], Tp);
		for(register int i = head[u]; i;i = e[i].nxt){
			int v = e[i].pre;
			if(v != fa[u] && v != son[u]) 
				DFS_Second(v, v);
		}
	}
	
	inline int LCA(int x, int y) {
		while(top[x] != top[y]) {
			if(dep[top[x]] < dep[top[y]]) Swap(x, y);
			x = fa[top[x]];
		}
		return dep[x] < dep[y] ? x : y;
	}
	
	inline void Updata(int x, int y, Line w) {
		while(top[x] != top[y]){
			if(dep[top[x]] < dep[top[y]]) Swap(x, y);
			ST::Updata(1, 1, n, dfn[top[x]], dfn[x], w);
			x = fa[top[x]];
		}
		if(dep[x] < dep[y]) Swap(x, y);
		ST::Updata(1, 1, n, dfn[y], dfn[x], w);
	}
	
	inline int Query(int x, int y) {
		int minn = 123456789123456789ll;
		while(top[x] != top[y]){
			if(dep[top[x]] < dep[top[y]]) Swap(x, y);
			minn = Min(minn, ST::Query(1, 1, n, dfn[top[x]], dfn[x]));
			x = fa[top[x]];
		}
		if(dep[x] < dep[y]) Swap(x, y);
		return Min(minn, ST::Query(1, 1, n, dfn[y], dfn[x]));
	}
	
}

#undef int
int main() {
#define int long long
//FileOpen();
	int m;
	io >> n >> m;
	R(i,2,n){
		int u, v, w;
		io >> u >> v >> w;
		add(u, v, w);
		add(v, u, w);
	}
	
	TP::DFS_First(1, 0);
	TP::DFS_Second(1, 1);
	ST::Build(n);
	
	while(m--){
		int opt;
		io >> opt;
		if(opt == 1){
			int u, v, a, b;
			io >> u >> v >> a >> b;
			int lca = TP::LCA(u, v);
			TP::Updata(u, lca, (Line){-a, b + ::dis[u] * a, 0});
			TP::Updata(v, lca, (Line){a, b + a * (::dis[u] - (::dis[lca] << 1)), 0});
		}
		else{
			int u, v;
			io >> u >> v;
			printf("%lld\n", TP::Query(u, v));
		}
	}
	
	return 0;
}

没看的了,咕了

posted @ 2019-10-11 16:40  邱涵的秘密基地  阅读(159)  评论(0编辑  收藏  举报