zoukankan      html  css  js  c++  java
  • P4069 [SDOI2016]游戏 [李超树,树链剖分]

    考虑到某个连续的段一定是离根的长度增加于是随便搞就行了,有点难调。

    // by Isaunoya
    #include<bits/stdc++.h>
    #define rep(i, x, y) for(int i = x; i <= y; ++i)
    #define Rep(i, x, y) for(int i = x; i >= y; --i)
    #define int long long
    using namespace std;
    struct io {
    	char buf[1 << 27 | 3], *s;
    	int f;
    	io() { f = 0, buf[fread(s = buf, 1, 1 << 27, stdin)] = '
    '; }
    	io& operator >> (int&x) {
    		for(x = f = 0; !isdigit(*s); ++s) f |= *s  == '-';
    		while(isdigit(*s)) x = x * 10 + (*s++ ^ 48);
    		return x = f ? -x : x, *this;
    	}
    };
    struct io_out {
    	char buf[1 << 27 | 3], *s = buf;
    	~io_out() { fwrite(buf, 1, s - buf, stdout); }
    	void write(int x) { if(x > 9) write(x / 10); *s++ = x % 10 ^ '0'; }
    	io_out& operator << (int x) {
    		if(x < 0) x = -x, *s++ = '-';
    		write(x); return *this;
    	}
    	io_out& operator << (char x) { *s++ = x; return *this; }
    } out;
    int n;
    const int maxn = 4e5 + 54;
    struct Edge {
    	int v, nxt, w;
    } e[maxn << 1];
    int head[maxn], cnt = 0;
    void add(int u, int v, int w) {
    	e[++ cnt] = { v, head[u], w }, head[u] = cnt;
    	e[++ cnt] = { u, head[v], w }, head[v] = cnt;
    }
    const int inf = 123456789123456789ll;
    struct Line {
    	int k, b;
    	Line(int _k = 0, int _b = inf) { k = _k, b = _b; }
    	int val(int x) { return k * x + b; }
    } a[maxn << 1];
    int fa[maxn], sz[maxn], dep[maxn], len[maxn], f[maxn][22], son[maxn];
    void dfs(int u) {
    	sz[u] = 1, dep[u] = dep[fa[u]] + 1;
    	for(int i = head[u], v = e[i].v; i; v = e[i = e[i].nxt].v) 
    		if(v != fa[u]) { fa[v] = u, len[v] = len[u] + e[i].w; dfs(v); sz[u] += sz[v]; if(sz[v] > sz[son[u]]) son[u] = v; }
    }
    int lca(int x, int y) {
    	if(dep[x] < dep[y]) swap(x, y);
    	for(int i = 20; ~i; --i) if(dep[f[x][i]] >= dep[y]) x = f[x][i]; if(x == y) return x;
    	for(int i = 20; ~i; --i) if(f[x][i] ^ f[y][i]) { x = f[x][i], y = f[y][i]; }
    	return f[x][0];
    }
    int top[maxn], idx = 0, dfn[maxn], rev[maxn];
    void dfs(int u, int t) {
    	top[u] = t, dfn[u] = ++idx; rev[dfn[u]] = u; if(son[u]) dfs(son[u], t);
    	for(int i = head[u], v = e[i].v; i; v = e[i = e[i].nxt].v) if(!top[v]) dfs(v, v);
    }
    struct LCT {
    	LCT() {}
    	int id[maxn << 2], mn[maxn << 2];
    	void up(int p) { mn[p] = min({mn[p], mn[p << 1], mn[p << 1 | 1]}); }
    	void build(int l, int r, int p) {
    		mn[p] = inf; id[p] = 0; if(l == r) { return ; }
    		int mid = l + r >> 1; build(l, mid, p << 1), build(mid + 1, r, p << 1 | 1); up(p);
    	}
    	void upd(int ql, int qr, int l, int r, int p, int x) {
    		int mid = l + r >> 1;
    		if(ql <= l && r <= qr) {
    			int &y = id[p]; 
    			int lx = a[x].val(len[rev[l]]), ly = a[y].val(len[rev[l]]);
    			int rx = a[x].val(len[rev[r]]), ry = a[y].val(len[rev[r]]);
    			if(lx <= ly && rx <= ry) { y = x; mn[p] = min({mn[p], lx, rx}); return; }
    			if(lx >= ly && rx >= ry) { return; }
    			int midx = a[x].val(len[rev[mid]]), midy = a[y].val(len[rev[mid]]);
    			if(midx <= midy) swap(x, y), swap(midx, midy), swap(lx, ly), swap(rx, ry);
    			if(lx <= ly) upd(ql, qr, l, mid, p << 1, x);
    			else upd(ql, qr, mid + 1, r, p << 1 | 1, x);
    			mn[p] = min({mn[p], lx, rx, ly, ry}), up(p); return;
    		}
    		if(ql <= mid) upd(ql, qr, l, mid, p << 1, x);
    		if(qr > mid) upd(ql, qr, mid + 1, r, p << 1 | 1, x);
    		up(p);
    	}
    	int qry(int ql, int qr, int l, int r, int p) {
    		if(ql <= l && r <= qr) { return mn[p]; }
    		int mid = l + r >> 1, ans = inf;
    		if(a[id[p]].b != inf) ans = min({ans, a[id[p]].val(len[rev[max(l, ql)]]), a[id[p]].val(len[rev[min(r, qr)]])});
    		if(ql <= mid) ans = min(ans, qry(ql, qr, l, mid, p << 1));
    		if(qr > mid) ans = min(ans, qry(ql, qr, mid + 1, r, p << 1 | 1)); 
    		return ans;
    	}
    } smt;
    int tot = 0;
    void upd(int x, int y) {
    	while(top[x] != top[y]) { smt.upd(dfn[top[x]], dfn[x], 1, n, 1, tot), x = fa[top[x]]; }
    	smt.upd(dfn[y], dfn[x], 1, n, 1, tot);
    }
    void mdf(int s, int t, int k, int b) {
    	int Lca = lca(s, t); a[++ tot] = Line(-k, k * len[s] + b); upd(s, Lca);
    	a[++ tot] = Line(k, k * (len[s] - (len[Lca] << 1)) + b); upd(t, Lca);
    }
    int qry(int x, int y) {
    	int ans = inf;
    	while(top[x] != top[y]) {
    		if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		ans = min(ans, smt.qry(dfn[top[x]], dfn[x], 1, n, 1)); x = fa[top[x]];
    	}
    	if(dep[x] > dep[y]) swap(x, y); ans = min(ans, smt.qry(dfn[x],dfn[y], 1, n, 1));
    	return ans;
    }
    signed main() {
    #ifdef LOCAL
    	freopen("testdata.in", "r", stdin);
    #endif
    	io in;
    	in >> n; int _; in >> _;
    	rep(i, 2, n) { int x, y, z; in >> x >> y >> z, add(x, y, z); }
    	dfs(1), dfs(1, 1); rep(i, 1, n) f[i][0] = fa[i]; rep(j, 1, 20) rep(i, 1, n) f[i][j] = f[f[i][j - 1]][j - 1];
    	smt.build(1, n, 1);
    	while(_ --) {
    		int op, s, t, a, b;
    		in >> op >> s >> t; if(op == 1) in >> a >> b;
    		if(op == 1) { mdf(s, t, a, b); } else { out << qry(s, t) << '
    '; }
    	}
    	return 0;
    }
    
  • 相关阅读:
    9、Spring Boot 2.x 集成 Thymeleaf
    【专题】Spring Boot 2.x 面试题
    8、Spring Boot 2.x 服务器部署
    7、Spring Boot 2.x 集成 Redis
    6、Spring Boot 2.x 集成 MyBatis
    5、Spring Boot 2.x 启动原理解析
    4、Spring Boot 2.x 自动配置原理
    3、Spring Boot 2.x 核心技术
    2、Spring Boot 2.x 快速入门
    centOS下安装JDK1.8.60,glassfish4.1.1以及MySQL
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12838829.html
Copyright © 2011-2022 走看看