BZOJ3924【树链剖分】【线段树】

来源:互联网 发布:linux 设置启动级别 编辑:程序博客网 时间:2024/05/18 14:23

每次暴力转移重心.

/* I will wait for you */#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>#include <algorithm>#include <iostream>#include <fstream>#include <vector>#include <queue>#include <deque>#include <set>#include <map>#include <string>#define make(a,b) make_pair(a,b)#define fi first#define se secondusing namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair<int, int> pii;typedef map<int, int> mii;const int maxn = 100010;const int maxm = 1010;const int maxs = 26;const int inf = 0x3f3f3f3f;const int P = 1000000007;const double error = 1e-9;inline ll read(){ll x = 0, f = 1; char ch = getchar();while (ch > '9' || ch < '0' )f = (ch == '-' ? -1 : 1), ch = getchar();while (ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();return f * x;}struct edge{int v, w, next;} e[2 * maxn];struct node{int l, r, sum;} t[4 * maxn];int n, m, cnt, dfn, root = 1, per[maxn], fa[maxn], dist[maxn],    mx[maxn], deep[maxn], size[maxn], pos[maxn], head[maxn];ll ans, tot;void insert(int u, int v, int w){e[cnt] = (edge) {v, w, head[u]}, head[u] = cnt++;e[cnt] = (edge) {u, w, head[v]}, head[v] = cnt++;}void dfs1(int u){size[u] = 1;for (int i = head[u]; i != -1; i = e[i].next) {int v = e[i].v;if (v != fa[u]) {fa[v] = u, deep[v] = deep[u] + 1;dist[v] = dist[u] + e[i].w;dfs1(v), size[u] += size[v];if (size[v] > size[mx[u]])mx[u] = v;}}}void dfs2(int u, int p){pos[u] = ++dfn, per[u] = p;if (mx[u])dfs2(mx[u], p);for (int i = head[u]; i != -1; i = e[i].next) {int v = e[i].v;if (v != fa[u] && v != mx[u])dfs2(v, v);}}int lca(int u, int v){while (per[u] != per[v]) {int pu = per[u], pv = per[v];if (deep[pu] < deep[pv])swap(u, v), swap(pu, pv);u = fa[pu];}if (deep[u] < deep[v])swap(u, v);return v;}int dis(int u, int v){int p = lca(u, v);return dist[u] + dist[v] - 2 * dist[p];}void build(int u, int l, int r){t[u].l = l, t[u].r = r;if (l != r) {int mid = (l + r) / 2;build(2 * u, l, mid);build(2 * u + 1, mid + 1, r);}}void change(int u, int x, int val){int l = t[u].l, r = t[u].r;if (l == r)t[u].sum += val;else {int mid = (l + r) / 2;if (x <= mid)change(2 * u, x, val);else change(2 * u + 1, x, val);t[u].sum = t[2 * u].sum + t[2 * u + 1].sum;}}int query(int u, int x, int y){int l = t[u].l, r = t[u].r;if (l >= x && r <= y)return t[u].sum;else {int mid = (l + r) / 2, res = 0;if (x <= mid)res += query(2 * u, x, y);if (y > mid)res += query(2 * u + 1, x, y);return res;}}ll solve(int u, int w){int t1, t2;if (u == fa[root]) {t1 = query(1, pos[root], pos[root] + size[root] - 1);t2 = tot - t1;}else {t2 = query(1, pos[u], pos[u] + size[u] -1);t1 = tot - t2;}return ans + (ll) (t1 - t2) * w;}void move(){ll tmp = (ll) inf * inf, t,  pos;for (int i = head[root]; i != -1; i = e[i].next) {int v = e[i].v; t = solve(v, e[i].w);if (t < tmp)tmp = t, pos = v;}if (tmp < ans)ans = tmp, root = pos, move();}int main(){n = read(), m = read(), build(1, 1, n);memset(head, -1, sizeof head);for (int i = 1; i < n; i++) {int u = read(), v = read(), w = read();insert(u, v, w);}dfs1(1), dfs2(1, 1);for (int i = 1; i <= m; i++) {int u = read(), w = read();ans += (ll) w * dis(u, root);tot += w, change(1, pos[u], w);move(), printf("%lld\n", ans);}return 0;}

0 0