SPOJ - QTREE Query on a tree 树链剖分

题目链接:

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=13013

题意:

给你一颗树,现在有两个操作,一种是改变某条边的权值,一种是查询点u到v之间的路径的最大边权。

题解:

树链剖分入门题。

我看的一些博客:

http://www.tuicool.com/articles/ee2QZf6

http://blog.csdn.net/y990041769/article/details/40348013

http://www.cnblogs.com/lidaxin/p/5184627.html

ppt:http://wenku.baidu.com/view/a088de01eff9aef8941e06c3.html

树链剖分只是把一些点映射到一个区间(一个重链相当于映射到了一个区间,轻链这是映射到了孤立的一些点),然后需要线段树或者rmq之类的数据结构基础来维护一些值。

主要代码就是两个dfs加一个solve(查询函数),两个dfs其实都挺简单的,中点把查询方法掌握了就基本ok了。

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<utility>
using namespace std;

const int maxn = 22222;
const int INF = 0x3f3f3f3f;

struct Edge {
    int u, v, w;
}egs[maxn];

vector<pair<int, int> > G[maxn];

int val[maxn], fat[maxn], dep[maxn], siz[maxn], son[maxn], top[maxn], id[maxn];
int n;

//求val,fat,dep,siz,son;
void dfs(int u, int f, int d, int va) {
    val[u] = va; fat[u] = f; dep[u] = d; siz[u] = 1;
    int ma = -INF;
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i].first;
        if (v == f) continue;
        dfs(v, u, d + 1, G[u][i].second);
        siz[u] += siz[v];
        if (ma < siz[v]) {
            son[u] = v; ma = siz[v];
        }
    }
}
//求top,id
int _tot;
void dfs2(int u, int f, int t) {
    top[u] = t; id[u] = ++_tot;
    if (son[u]) dfs2(son[u], u, t);
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i].first;
        if (v == f || v == son[u]) continue;
        //轻链的下端点top等于它自己
        dfs2(v, u, v);
    }
}

#define lson (o<<1)
#define rson ((o<<1)|1)
#define M (l+(r-l)/2)
int maxv[maxn << 2];

int _p, _v;
void update(int o, int l, int r) {
    if (l == r) {
        maxv[o] = _v;
    }
    else {
        if (_p <= M) update(lson, l, M);
        else update(rson, M + 1, r);
        maxv[o] = max(maxv[lson], maxv[rson]);
    }
}

int ql, qr, _max;
void query(int o, int l, int r) {
    if (ql <= l&&r <= qr) {
        _max = max(_max, maxv[o]);
    }
    else {
        if (ql <= M) query(lson, l, M);
        if (qr > M) query(rson, M + 1, r);
    }
}

//
int solve(int u, int v) {
    int f1 = top[u], f2 = top[v];
    int ret = -INF;
    while (f1 != f2) {
        //printf("f1:%d,f2:%d\n", f1, f2);
        if (dep[f1] < dep[f2]) {
            swap(f1, f2);
            swap(u, v);
        }
        ql = id[f1], qr = id[u], _max = -INF;
        query(1, 1, n);
        ret = max(ret, _max);
        u = fat[f1];
        f1 = top[u];
    }
    //printf("u:%d,v:%d\n", u, v);
    if (u == v) return ret;
    if (dep[u] > dep[v]) swap(u, v);
    ql = id[son[u]], qr = id[v], _max = -INF;
    query(1, 1, n);
    ret = max(ret, _max);
    return ret;
}

void init() {
    for (int i = 1; i <= n; i++) G[i].clear();
    memset(son, 0, sizeof(son));
    _tot = 0;
}

int main() {
    int tc;
    scanf("%d", &tc);
    while (tc--) {
        scanf("%d", &n);
        init();
        for (int i = 1; i < n; i++) {
            scanf("%d%d%d", &egs[i].u, &egs[i].v, &egs[i].w);
            G[egs[i].u].push_back(make_pair(egs[i].v, egs[i].w));
            G[egs[i].v].push_back(make_pair(egs[i].u, egs[i].w));
        }
        dfs(1, -1, 1, -INF);
        dfs2(1, -1, 1);
        //for (int i = 1; i <= n; i++) printf("id:%d\n", id[i]);
        for (int i = 1; i <= n; i++) {
            _p = id[i], _v = val[i];
            update(1, 1, n);
        }
        char cmd[11];
        int x, y;
        while (scanf("%s", cmd) == 1) {
            if (cmd[0] == 'D') break;
            scanf("%d%d", &x, &y);
            if (cmd[0] == 'Q') {
                printf("%d\n", solve(x, y));
            }
            else if (cmd[0] == 'C') {
                int t = fat[egs[x].v] == egs[x].u ? egs[x].v : egs[x].u;
                _p = id[t], _v = y;
                update(1, 1, n);
            }
        }
        if(tc) puts("");
    }
    return 0;
}

/*
4
1 2 1
1 3 2
3 4 3
QUERY 1 2
QUERY 1 3
QUERY 3 4
DONE
*/

 

posted @ 2016-05-29 02:01  fenicnn  阅读(1193)  评论(0编辑  收藏  举报