http://47.92.197.167:5283/contest/454/problem/1
我们其实就是要在树上从根到某个点的路径维护从任意地方开始的:
而这东西,是典型的兔队线段树形式
我们只需要把询问离线,然后拿线段树维护当前点到根的路径即可
// ubsan: undefined
// accoders
#include
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stdout, ##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
#define fi first
#define se second
//#define M
#define mo (int)(1e9 + 7)
#define N 300010
struct node { int y, z; };
struct quey { int x, id; };
vector<node>G[N];
vector<quey>E[N];
int n, m, i, j, k, T, u, v, w, ans[N];
int dfn[N], dep[N];
struct Segment_tree {
#define ls (k << 1)
#define rs (k << 1 | 1)
#define mid ((l + r) >> 1)
int mn[N << 2], s[N << 2], ans[N << 2];
pair<int, int> que(int k, int l, int r, int x, int y, int lst) {
if(l >= x && r <= y) {
if(l == r) return {s[k] * lst, mn[k]};
if(lst <= mn[k]) return {s[k] * lst, mn[k]};
if(lst <= mn[ls]) {
auto t = que(rs, mid + 1, r, x, y, lst);
int sum = s[ls] * lst + t.fi;
return {sum, min(lst, mn[k])};
}
else {
auto t = que(ls, l, mid, x, y, lst);
int sum = t.fi + ans[k] - ans[ls];
return {sum, min(lst, mn[k])};
}
return {0, 0};
}
int sum = 0, mx = 1e18;
if(x <= mid) {
auto t = que(ls, l, mid, x, y, lst);
sum += t.fi; mx = t.se;
}
if(y >= mid + 1) {
auto t = que(rs, mid + 1, r, x, y, min(lst, mx));
sum += t.fi; mx = min(mx, t.se);
}
return {sum, mx};
}
void push_up(int k, int l, int r) {
s[k] = s[ls] + s[rs];
mn[k] = min(mn[ls], mn[rs]);
ans[k] = ans[ls] + que(rs, mid + 1, r, mid + 1, r, mn[ls]).fi;
}
void set(int k, int l, int r, int x, int Mn, int S) {
if(l == r) {
mn[k] = Mn; s[k] = S; ans[k] = 0;
return ;
}
if(x <= mid) set(ls, l, mid, x, Mn, S);
else set(rs, mid + 1, r, x, Mn, S);
push_up(k, l, r);
}
#undef ls
#undef rs
#undef mid
}Seg;
void dfs1(int x, int fa) {
dep[x] = dep[fa] + 1;
for(auto t : G[x]) if(t.y != fa) dfs1(t.y, x);
}
void dfs2(int x, int fa, int w) {
dfn[x] = dep[x];
// debug("%lld : %lld\n", x, dep[x]);
Seg.set(1, 1, n, dfn[x], x, w);
for(auto t : G[x]) if(t.y != fa) dfs2(t.y, x, t.z);
for(auto t : E[x]) {
int y = t.x;
// debug("%lld -> %lld\n", y, x);
if(dfn[y] <= 0) { ans[t.id] = -1; continue; }
ans[t.id] = Seg.que(1, 1, n, dfn[y] + 1, dfn[x], y).fi;
}
dfn[x] = -1;
}
signed main()
{
// #ifdef LOCAL
freopen("tree.in", "r", stdin);
freopen("tree.out", "w", stdout);
// #endif
// srand(time(NULL));
// T=read();
// while(T--) {
//
// }
n = read(); m = read();
for(i = 1; i < n; ++i) {
u = read(); v = read(); w = read();
G[u].pb({v, w}); G[v].pb({u, w});
}
dfs1(1, 0);
for(i = 1; i <= m; ++i) {
u = read(); v = read();
if(u == v) { ans[i] = 0; continue; }
// if(dep[u] > dep[v]) swap(u, v);
E[v].pb({u, i});
}
dfs2(1, 0, 0);
for(i = 1; i <= m; ++i) printf("%lld\n", ans[i]);
return 0;
}