题目大意:给定一棵树。有三种操作:
- $0;u;v;t:$在$u$到$v$的链上进行重要度为$t$的数据传输。
- $1;x:$结束第$x$个时刻的数据传输(保证合法)。
- $2;x:$询问不经过点$x$的数据传输中重要度最大的是多少(无解输出$-1$)。
题解:可以发现一条路径对所有不在这条路径上的点有贡献,所以可以把这些区间给排除(树链剖分中的每一条链存下来),把其他位置加上一个数,可以给每个点维护一个大根堆。
考虑删除一个数,可以再开一个大根堆,表示删除的数,若两个堆顶元素相同,就弹出。
卡点:无
C++ Code:
#include <algorithm> #include <cstdio> #include <queue> #include <iostream> #define maxn 100010 inline int min(int a, int b) {return a < b ? a : b;} inline int max(int a, int b) {return a > b ? a : b;} int head[maxn], cnt; struct Edge { int to, nxt; } e[maxn << 1]; inline void add(int a, int b) { e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt; } int n, m; namespace SgT { struct node { std::priority_queue<int> A, D; inline void push(int x) {A.push(x);} inline void del(int x) {D.push(x);} inline int top() { while (!A.empty() && !D.empty() && A.top() == D.top()) A.pop(), D.pop(); return A.empty() ? -1 : A.top(); } } V[maxn << 2]; int L, R, num, op; void modify(int rt, int l, int r) { if (L <= l && R >= r) { if (op) V[rt].push(num); else V[rt].del(num); return ; } int mid = l + r >> 1; if (L <= mid) modify(rt << 1, l, mid); if (R > mid) modify(rt << 1 | 1, mid + 1, r); } void add(int __L, int __R, int __num) { L = __L, R = __R, num = __num, op = 1; modify(1, 1, n); } void del(int __L, int __R, int __num) { L = __L, R = __R, num = __num, op = 0; modify(1, 1, n); } int __ask(int rt, int l, int r) { if (l == r) return V[rt].top(); int mid = l + r >> 1, ans = V[rt].top(); if (L <= mid) return max(ans, __ask(rt << 1, l, mid)); else return max(ans, __ask(rt << 1 | 1, mid + 1, r)); } int ask(int __L) { L = __L; return __ask(1, 1, n); } } using SgT::add; using SgT::del; using SgT::ask; int fa[maxn], dep[maxn], sz[maxn]; int dfn[maxn], idx, top[maxn], son[maxn]; void dfs1(int u) { sz[u] = 1; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v != fa[u]) { fa[v] = u; dep[v] = dep[u] + 1; dfs1(v); sz[u] += sz[v]; if (!son[u] || sz[v] > sz[son[u]]) son[u] = v; } } } void dfs2(int u) { dfn[u] = ++idx; int v = son[u]; if (v) top[v] = top[u], dfs2(v); for (int i = head[u]; i; i = e[i].nxt) { v = e[i].to; if (v != fa[u] && v != son[u]) { top[v] = v; dfs2(v); } } } struct Modify { int u, v, x; } Mo[200010]; struct List { int l, r; inline friend bool operator < (const List &lhs, const List &rhs) { return lhs.l < rhs.l; } } S[maxn]; void modify(int u, int v, int x, int op = 1) { int top = 0; while (::top[u] != ::top[v]) { if (dfn[::top[u]] < dfn[::top[v]]) std::swap(u, v); S[top++] = (List) {dfn[::top[u]], dfn[u]}; u = fa[::top[u]]; } if (dfn[u] > dfn[v]) std::swap(u, v); S[top++] = (List) {dfn[u], dfn[v]}; std::sort(S, S + top); int reach = 1; for (int i = 0; i < top; reach = max(reach, S[i++].r + 1)) if (reach < S[i].l) { if (op) add(reach, S[i].l - 1, x); else del(reach, S[i].l - 1, x); } if (reach <= n) { if (op) add(reach, n, x); else del(reach, n, x); } } int main() { std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); std::cin >> n >> m; for (int i = 1, a, b; i < n; i++) { std::cin >> a >> b; add(a, b); add(b, a); } dfs1(1); top[1] = 1; dfs2(1); for (int i = 1; i <= m; i++) { int op, x, y, z; std::cin >> op >> x; switch (op) { case 0: std::cin >> y >> z; Mo[i] = (Modify) {x, y, z}; modify(x, y, z); break; case 1: modify(Mo[x].u, Mo[x].v, Mo[x].x, 0); break; case 2: std::cout << ask(dfn[x]) << ' '; break; } } return 0; }