题目链接:Query on a tree
题目大意
一棵树,有n个节点n<=1e4, 有两种操作:1.求节点a和b之间路径的最大权值的边;2. 将边i的权值改为ti
思路
树链剖分,边的权值存在儿子节点上,线段树求区间值和修改
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e4 + 10, inf = 0x3f3f3f3f;
int n, mx[maxn << 2];
int cost[maxn];
struct edge
{
int to, cost, nxt;
edge(int to = 0, int cost = 0, int nxt = 0)
{
this->to = to;
this->cost = cost;
this->nxt = nxt;
}
};
edge es[maxn * 2];
int head[maxn];
inline void addedge(int id, int u, int v, int cost)
{
es[id * 2] = edge(v, cost, head[u]);
head[u] = id * 2;
es[id * 2 + 1] = edge(u, cost, head[v]);
head[v] = id * 2 + 1;
}
#define ls l, m, rt<<1
#define rs m+1, r, rt<<1|1
inline void pushUp(int rt)
{
mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
}
void build(int l, int r, int rt)
{
if (l == r)
{
mx[rt] = cost[l];
return;
}
int m = (l + r) >> 1;
build(ls);
build(rs);
pushUp(rt);
}
void update(int p, int v, int l, int r, int rt)
{
if (l == r)
{
mx[rt] = v;
return;
}
int m = (l + r) >> 1;
if (p <= m) update(p, v, ls);
else update(p, v, rs);
pushUp(rt);
}
int query(int L, int R, int l, int r, int rt)
{
if (L <= l && r <= R) return mx[rt];
if (l > R || r < L) return -inf;
int m = (l + r) >> 1;
return max(query(L, R, ls), query(L, R, rs));
}
int siz[maxn];
int top[maxn];
int son[maxn];
int dep[maxn];
int faz[maxn];
int id[maxn];
int rid[maxn];
int dfs_clocks;
void init(int n)
{
memset(head, 0, sizeof(int) * (n + 1));
memset(son , -1, sizeof(int) * (n + 1));
dfs_clocks = 1;
}
void dfs1(int u, int fa, int depth)
{
dep[u] = depth;
faz[u] = fa;
siz[u] = 1;
for (int i = head[u]; i; i = es[i].nxt)
{
int v = es[i].to;
if (v == fa) continue;
dfs1(v, u, depth + 1);
siz[u] += siz[v];
if (son[u] == -1 || siz[v] > siz[son[u]]) son[u] = v;
}
}
void dfs2(int u, int tp)
{
top[u] = tp;
id[u] = dfs_clocks;
rid[dfs_clocks++] = u;
if (son[u] == -1) return;
dfs2(son[u], tp);
for (int i = head[u]; i; i = es[i].nxt)
{
int v = es[i].to;
if (v != son[u] && v != faz[u]) dfs2(v, v);
}
}
int query_path(int x, int y)
{
int ret = -inf;
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ret = max(ret, query(id[top[x]], id[x], 1, n, 1));
x = faz[top[x]];//error: x = faz[x];
}
if (x != y)
{
if (id[x] > id[y]) swap(x, y);
ret = max(ret, query(id[son[x]], id[y], 1, n, 1));
}
return ret;
}
void update_path(int eid, int v)
{
int x = dep[es[eid * 2].to] > dep[es[eid * 2 + 1].to] ?
es[eid * 2].to : es[eid * 2 + 1].to;
update(id[x], v, 1, n, 1);//error: update(x, v, 1, n, 1);
}
int main()
{
int T;
for (scanf("%d", &T); T; --T)
{
scanf("%d", &n);
init(n);
int a, b, c;
for (int i = 1; i < n; ++i)
{
scanf("%d%d%d", &a, &b, &c);
addedge(i, a, b, c);
}
dfs1(1, 1, 1);
dfs2(1, 1);
for (int i = 1; i <= n - 1; ++i)
{
int x = dep[es[i * 2].to] > dep[es[i * 2 + 1].to] ?
es[i * 2].to : es[i * 2 + 1].to;
cost[id[x]] = es[i * 2].cost;
}
build(1, n, 1);
char q[20];
while (scanf("%s", q))
{
if (q[0] == 'Q')
{
scanf("%d%d", &a, &b);
printf("%d\n", query_path(a, b));
}
else if (q[0] == 'C')
{
scanf("%d%d", &a, &b);
update_path(a, b);
}
else break;
}
}
return 0;
}