spoj375 Query on a tree 树链剖分

来源:互联网 发布:张伯伦数据统计 编辑:程序博客网 时间:2024/05/17 02:56

题目大意

链接请点我
给一棵树,有两种操作,一种是改变某一条边的边权,一种是询问某两个结点间的路径的最大值

解题

具体思路参见2009年集训队漆子超的论文《分治算法在树的路径问题中的应用》
树链剖分裸题,无奈昨天一直TLE,非常怨念,今天重写了一发,居然A了,虽然也不快,3.89s
感觉我用的姿势应该是能看得下去的……

CODE

#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int maxn = 10010;const int inf = 0x3fffffff;int max(int a, int b) {    return a > b ? a : b;}struct edge {    int v, next;    edge() {}    edge(int a, int b) : v(a), next(b) {}};edge e[maxn*3];struct data {    int x, y, d;};data E[maxn<<1];int head[maxn], son[maxn], sz[maxn], pre[maxn], top[maxn], dep[maxn], hash[maxn];int n, num, tot;void add(int u, int v) {    e[tot] = edge(v, head[u]); head[u] = tot++;    e[tot] = edge(u, head[v]); head[v] = tot++;}void dfs(int u, int d) {    sz[u] = 1; son[u] = 0; dep[u] = d;    for (int i = head[u]; ~i; i = e[i].next) {        int v = e[i].v;        if (v == pre[u]) continue;        pre[v] = u;        dfs(v, d+1);        sz[u] += sz[v];        if (sz[v] > sz[son[u]]) son[u] = v;    }}void build_tree(int u, int fa) {    hash[u] = ++num; top[u] = fa;    if (son[u]) build_tree(son[u], top[u]);    for (int i = head[u]; ~i; i = e[i].next) {        int v = e[i].v;        if (v == pre[u] || v == son[u]) continue;        build_tree(v, v);    }}#define lson l, m, rt<<1#define rson m+1, r, rt<<1|1int mx[maxn<<2];void PushUp(int rt) {    mx[rt] = max(mx[rt<<1], mx[rt<<1|1]);}void build(int l, int r, int rt) {    mx[rt] = -inf;    if (l == r) return;    int m = (l+r) >> 1;    build(lson); build(rson);}void update(int pos, int x, int l, int r, int rt) {    if (l == r) {        mx[rt] = x;        return;    }    int m = (l+r) >> 1;    if (pos <= m) update(pos, x, lson);    else update(pos, x, rson);    PushUp(rt);}int query(int ll, int rr, int l, int r, int rt) {    if (ll <= l && rr >= r) return mx[rt];    int m = (l+r) >> 1;    int res = -inf;    if (ll <= m) res = max(res, query(ll, rr, lson));    if (rr > m) res = max(res, query(ll, rr, rson));    return res;}int Query(int x, int y) {    int ans = -inf;    while (top[x] != top[y]) {        if (dep[top[x]] < dep[top[y]]) swap(x, y);        ans = max(ans, query(hash[top[x]], hash[x], 2, n, 1));        x = pre[top[x]];    }    if (dep[x] > dep[y]) swap(x, y);    if (x != y)        ans = max(ans, query(hash[x]+1, hash[y], 2, n, 1));    return ans;}void solve() {    scanf("%d", &n);    memset(head, -1, sizeof(head));    tot = 0;    for (int i = 1; i < n; i++) {        scanf("%d%d%d", &E[i].x, &E[i].y, &E[i].d);        add(E[i].x, E[i].y);    }    sz[0] = 0; num = 0;    dfs(1, 1);    build_tree(1, 1);    build(2, n, 1);    for (int i = 1; i < n; i++) {        if (dep[E[i].x] < dep[E[i].y]) swap(E[i].x, E[i].y);        update(hash[E[i].x], E[i].d, 2, n, 1);    }    char op[10];    while (1) {        scanf("%s", op);        if (op[0] == 'D') break;        int x, y;        scanf("%d%d", &x, &y);        if (op[0] == 'C') update(hash[E[x].x], y, 2, n, 1);        else if (op[0] == 'Q') printf("%d\n", Query(x, y));    }}int main() {    int cs; scanf("%d", &cs);    while (cs--) solve();    return 0;}


0 0
原创粉丝点击