您的位置:首页 > 产品设计 > UI/UE

SPOJ 375 Query on a tree (树链剖分+线段树)

2015-07-22 10:47 423 查看

题意:

给出一棵树,有两种操作:

询问[u,v][u,v]的最大权值

然后更改第ii条边的权值为valval

解析:

这是树链剖分的入门题,昨天调试了半天才做出这题,我还是太弱了。>但是还是弄懂了什么是树链剖分


树链剖分有先要进行两次dfs操作进行初始化。


第一个初始化操作,求得是每个节点的开头fa[u],每个节点的深度deep[u],以及每个节点的重儿子son[u]。


第二个初始化操作,求得是重链的头top[u],以及在每个节点在线段树中的位置id[u]。


为什么树链剖分会更快?

因为每次询问的时候,查询的点都是跳到重链的头,这样类似一个跳表,这样减少了中间访问的次数


怎么询问[u,v]的最值?

(1) 记tp1=top[u]tp1 = top[u],tp2=top[v]tp2 = top[v]。

(2) 当tp1!=tp2tp1 != tp2时:不妨设dep[tp1]>=dep[tp2]dep[tp1] >= dep[tp2],那么就更新u到tp1的父边的权值(log(n)log(n)),并使u=fa[tp1]u = fa[tp1]。

(3) 当tp1=tp2tp1 = tp2时:u与v在同一条重链上,若u与v不是同一点,就更新u到v路径上的边的权值(log(n)log(n)),否则修改完成。


查询的时候用线段树维护的是,当前点u,在线段树中的位置id[u]id[u],以及重链的头tp1,在线段树中的位置id[tp1]id[tp1],查询的就是区间就是 [id[u],id[tp1]][id[u],id[tp1]]

mymy codecode

[code]#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls, L, M
#define rson rs, M+1, R
using namespace std;
const int N = 10005;

struct Edge {
    int u, v, val;
    Edge() {}
    Edge(int u, int v, int val) : u(u), v(v), val(val) {}
} edge
;

int n;

vector<int> G
;

int deep
, size
, fa
, id
, son
, top
;
int dfs_clock;

void init() {
    for(int i = 0; i <= n; i++) G[i].clear();
}

void addEdge(int u, int v) {
    G[u].push_back(v);
}

void dfs1(int u, int pre, int de) {
    deep[u] = de;
    size[u] = 1;
    son[u] = 0;
    fa[u] = pre;
    for(int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if(pre == v) continue;
        dfs1(v, u, de+1);
        if(size[son[u]] < size[v]) 
            son[u] = v;
    }
}

void dfs2(int u, int tp) {
    top[u] = tp;
    id[u] = ++dfs_clock;
    if(son[u]) dfs2(son[u], tp);
    for(int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if(v == fa[u] || v == son[u]) continue;
        dfs2(v, v);
    }
}

int maxv[N<<2];
inline void pushUp(int o) {
    maxv[o] = max(maxv[ls], maxv[rs]);
}

void build(int o, int L, int R) {
    maxv[o] = 0;
    if(L == R) return ;
    int M = (L + R)/2;
    build(lson);
    build(rson);
    pushUp(o);
}

void modify(int o, int L, int R, int pos, int val) {
    if(L == R) {
        maxv[o] = val;
        return ;
    }
    int M = (L + R)/2;
    if(pos <= M) modify(lson, pos, val);
    else modify(rson, pos, val);
    pushUp(o);
}

int query(int o, int L, int R, int ql, int qr) {
    if(ql <= L && R <= qr) return maxv[o];
    int M = (L + R)/2, ret = 0;
    if(ql <= M) ret = max(ret, query(lson, ql, qr));
    if(qr > M) ret = max(ret, query(rson, ql, qr));
    return ret;
}

int find(int u, int v) {
    int tp1 = top[u], tp2 = top[v];
    int ans = 0;
    while(tp1 != tp2) {
        if(deep[tp1] < deep[tp2]) {
            swap(tp1, tp2);
            swap(u, v);
        }
        ans = max(ans, query(1, 1, dfs_clock, id[tp1], id[u]));
        u = fa[tp1];
        tp1 = top[u];
    }
    if(u == v) return ans;
    if(deep[u] > deep[v]) swap(u, v);
    return max(ans, query(1, 1, dfs_clock, id[son[u]], id[v]));
}

int main() {
    //freopen("in.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        init();
        int u, v, val;
        for(int i = 1; i < n; i++) {
            scanf("%d%d%d", &u, &v, &val);
            edge[i] = Edge(u, v, val);
            addEdge(u, v);
            addEdge(v, u);
        }

        dfs_clock = 0;
        dfs1(1, 0, 1);
        dfs2(1, 1);
        build(1, 1, dfs_clock);

        for(int i = 1; i < n; i++) {
            if(deep[edge[i].v] < deep[edge[i].u])
                swap(edge[i].v, edge[i].u);
            modify(1, 1, dfs_clock, id[edge[i].v], edge[i].val);
        }

        char oper[10];
        while(~scanf("%s", oper)) {
            if(oper[0] == 'D') break;
            if(oper[0] == 'Q') {
                scanf("%d%d", &u, &v);
                printf("%d\n", find(u, v));
            }else if(oper[0] == 'C') {
                scanf("%d%d", &u, &val);
                modify(1, 1, dfs_clock, id[edge[u].v], val);
            }
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: