# BZOJ4732. [清华集训2016]数据交互（树链剖分＋线段树＋multiset）

## 题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=4732

## 题解

• 对于链的插入操作，插入权值为 $w$ 的链 $(x, y)$ 时，我们只需使 $a_{{\rm lca}_{x, y}}$ 增加 $w$，链 $(x, y)$ 上除 ${\rm lca}_{x, y}$ 的所有点的 $b$ 增加 $w$
• 对于链的删除操作，我们只需将链的权值改为 $-w$ 即可，其余操作同插入操作
• 对于查询操作，根据最开始给出的结论，对于一条路径 $(x, y)$，所能得到的权值和即为路径上所有结点的 $a$ 数值之和再加上 $b_{{\rm lca}_{x, y}}$

## 代码

#include<bits/stdc++.h>

using namespace std;

#define rg register

typedef long long ll;

template<typename T> inline bool checkMax(T& a, const T& b) {
return a < b ? a = b, true : false;
}

const int N = 1e5 + 10;

struct Edge {
Edge* next;
int to;
Edge () {}
Edge (Edge* next, int to): next(next), to(to) {}
} *first[N], pool[N << 1], *pis = pool;

inline void add(int u, int v) {
first[u] = new (pis++) Edge (first[u], v);
first[v] = new (pis++) Edge (first[v], u);
}

int n, m, size[N], pa[N], heavy[N], top[N], dfn[N], arc_dfn[N], dfn_cnt, end_p[N], dep[N];
multiset<ll> ans, g[N];

inline void dfs1(int u, int pa) {
size[u] = 1;
int v = 0;
for (Edge* now = first[u]; now; now = now->next) {
if (now->to ^ pa) {
::pa[now->to] = u;
dep[now->to] = dep[u] + 1;
dfs1(now->to, u);
size[u] += size[now->to];
if (checkMax(v, size[now->to])) {
heavy[u] = now->to;
}
}
}
}

inline void dfs2(int u, int t) {
top[u] = t;
dfn[u] = end_p[u] = ++dfn_cnt, arc_dfn[dfn_cnt] = u;
if (heavy[u]) {
dfs2(heavy[u], t);
end_p[u] = end_p[heavy[u]];
} else {
ans.insert(0);
}
for (Edge* now = first[u]; now; now = now->next) {
if (now->to ^ pa[u] && now->to ^ heavy[u]) {
g[u].insert(0);
dfs2(now->to, now->to);
}
}
}

#define lo (o<<1)
#define ro (o<<1|1)

struct State {
ll lv, rv, maxv, sumv;
State () {
lv = rv = maxv = sumv = 0;
}
inline State operator + (const State& a) const {
State res;
res.lv = max(lv, sumv + a.lv);
res.rv = max(a.rv, a.sumv + rv);
res.sumv = sumv + a.sumv;
res.maxv = max(max(maxv, a.maxv), rv + a.lv);
return res;
}
} s[N << 2];

ll a[N << 2], addv[N << 2];

inline void add_tag(int o, ll v) {
s[o].rv += v;
s[o].maxv += v;
}

inline void push_down(int o) {
}
}

inline void modify_s(int l, int r, int o, int p, ll v) {
if (l == r) {
int u = arc_dfn[l];
a[o] += v, s[o].sumv = a[o];
multiset<ll>:: iterator it = g[u].end();
ll res = 0;
if (g[u].size() >= 1) {
res += *--it;
}
s[o].lv = a[o] + res;
s[o].rv = a[o] + res + addv[o];
if (g[u].size() >= 2) {
res += *--it;
}
s[o].maxv = res + a[o] + addv[o];
} else {
int mid = l + r >> 1;
push_down(o);
(p <= mid) ? modify_s(l, mid, lo, p, v) : modify_s(mid + 1, r, ro, p, v);
s[o] = s[lo] + s[ro];
}
}

inline void modify_tag(int l, int r, int o, int ql, int qr, ll v) {
if (ql <= l && r <= qr) {
} else {
int mid = l + r >> 1;
push_down(o);
if (ql <= mid) {
modify_tag(l, mid, lo, ql, qr, v);
} if (qr > mid) {
modify_tag(mid + 1, r, ro, ql, qr, v);
}
s[o] = s[lo] + s[ro];
}
}

inline State query(int l, int r, int o, int ql, int qr) {
if (ql <= l && r <= qr) {
return s[o];
} else {
int mid = l + r >> 1;
push_down(o);
if (qr <= mid) {
return query(l, mid, lo, ql, qr);
} else if (ql > mid) {
return query(mid + 1, r, ro, ql, qr);
} else {
return query(l, mid, lo, ql, qr) + query(mid + 1, r, ro, ql, qr);
}
}
}

inline void jump(int u, ll tmp, int lca, int w) {
for (; u; u = pa[top[u]]) {
int l = lca ? max(dfn[lca] + 1, dfn[top[u]]) : n + 1, r = dfn[u];
int p = pa[top[u]];
if (p) {
State x = query(1, n, 1, dfn[top[p]], end_p[p]);
ans.erase(ans.lower_bound(x.maxv));
g[p].erase(g[p].lower_bound(tmp));
tmp = x.lv;
}
if (l <= r) {
ans.erase(ans.lower_bound(query(1, n, 1, dfn[top[u]], end_p[u]).maxv));
modify_tag(1, n, 1, l, r, w);
ans.insert(query(1, n, 1, dfn[top[u]], end_p[u]).maxv);
}
if (p) {
g[p].insert(query(1, n, 1, dfn[top[u]], end_p[u]).lv);
modify_s(1, n, 1, dfn[p], 0);
ans.insert(query(1, n, 1, dfn[top[p]], end_p[p]).maxv);
}
}
}

inline void modify(int u, int v, int w) {
int old_u = u, old_v = v, lca;
for (; top[u] ^ top[v]; u = pa[top[u]]) {
if (dep[top[u]] < dep[top[v]]) {
swap(u, v);
}
}
lca = dep[u] <= dep[v] ? u : v;
u = old_u, v = old_v;
jump(u, query(1, n, 1, dfn[top[u]], end_p[u]).lv, lca, w);
jump(v, query(1, n, 1, dfn[top[v]], end_p[v]).lv, lca, w);
State x = query(1, n, 1, dfn[top[lca]], end_p[lca]);
ans.erase(ans.lower_bound(x.maxv));
modify_s(1, n, 1, dfn[lca], w);
ans.insert(query(1, n, 1, dfn[top[lca]], end_p[lca]).maxv);
jump(lca, x.lv, 0, 0);
}

int req_u[N], req_v[N], req_w[N];

int main() {
scanf("%d%d", &n, &m);
for (rg int i = 1; i < n; ++i) {
int u, v; scanf("%d%d", &u, &v);
}
dfs1(1, 0);
dfs2(1, 1);
for (rg int i = 1; i <= m; ++i) {
char cmd[4];
scanf("%s", cmd);
if (*cmd == '+') {
scanf("%d%d%d", &req_u[i], &req_v[i], &req_w[i]);
modify(req_u[i], req_v[i], req_w[i]);
} else {
int tim; scanf("%d", &tim);
modify(req_u[tim], req_v[tim], -req_w[tim]);
}
printf("%lld\n", *ans.rbegin());
}
return 0;
}

posted @ 2018-11-22 07:39  ImagineC  阅读(520)  评论(4编辑  收藏