zoukankan      html  css  js  c++  java
  • 总结-李超线段树

    概念

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

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

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

    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("
    ----------
    ")
    #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, "
    time: %.3fms
    ", 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
    ", (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("
    -----------
    ")
    #define D_e(x) std::cerr << (#x) << " : " <<x << "
    "
    #define FileOpen() freopen("in.txt", "r", stdin)
    #define FileSave() freopen("out.txt", "w", stdout)
    #define Pause() system("pause")
    #include <ctime>
    #define TIME() fprintf(stderr, "
    TIME : %.3lfms
    ", 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
    ", TP::Query(u, v));
    		}
    	}
    	
    	return 0;
    }
    

    没看的了,咕了

  • 相关阅读:
    wampServer多站点配置
    wamp中根目录自定义
    [学习笔记] 七步从Angular.JS菜鸟到专家(2):Scopes [转]
    [学习笔记] 七步从Angular.JS菜鸟到专家(1):如何开始 [转]
    [学习笔记] Python标准库简明教程 [转]
    [学习笔记] Python标准库的学习准备 [转]
    [学习笔记] socket通信简介 [转]
    [学习笔记] 国内主流php框架比较 [转]
    [学习笔记] symfony核心类 [转]
    [学习笔记] Symfony2安全机制
  • 原文地址:https://www.cnblogs.com/bingoyes/p/11655123.html
Copyright © 2011-2022 走看看