P4069 [SDOI2016]游戏 [李超树,树链剖分]
Posted isaunoya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}
以上是关于P4069 [SDOI2016]游戏 [李超树,树链剖分]的主要内容,如果未能解决你的问题,请参考以下文章