spoj375Query on a tree树链剖分

学了下树链剖分,这个链接讲的很详细http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html

就是把一颗树划分轻重链,然后标号,对应到一颗线段树上。更新a到b的路径时,就把在下面的向上提 直到在一条重链上或者两点重合。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <string.h>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1


const int maxn = 111111;
struct Node
{
    int to;int val;int next;
}e[maxn];
int edge[maxn][3];
int len ;
int z; ;
int son[maxn];
int father[maxn];
int size[maxn];
int deep[maxn];
int pos[maxn],top[maxn];
int Max[maxn<<2];
int head[maxn];
void add(int from, int to, int val)
{
    e[len].to = to;
    e[len].val = val;
    e[len].next = head[from];
    head[from] = len++;
}


void init(int x)
{
    size[x] = 1; son[x] = 0;
    for (int i = head[x]; i != -1; i = e[i].next){
        int cc = e[i].to;
        if (cc == father[x]) continue;
        father[cc] = x; deep[cc] = deep[x] + 1;
        init(cc);
        if (size[cc] > size[son[x]]) son[x] = cc;
        size[x]+=size[cc];
    }
}

void dfs(int x, int tp)
{
    pos[x] = ++z; top[x] = tp;
    if (son[x]) dfs(son[x], tp);
    for (int i = head[x]; i != -1; i = e[i].next){
        int cc = e[i].to;
        if (cc == son[x] || cc == father[x]) continue;
        dfs(cc, cc);
    }
}

void up(int rt)
{
    Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
}
void update(int pos, int key, int l, int r, int rt)
{
    if (l == r){
        Max[rt] = key; return;
    }
    int mid = (l + r) >> 1;
    if (pos <= mid) update(pos, key, lson);
    else update(pos, key, rson);
    up(rt);
}

int ask(int L, int R, int l, int r, int rt)
{
    if (L <= l&&r <= R) return Max[rt];
    int mid = (l + r) >> 1;
    int ans = -1;
    if (L <= mid) ans = max(ans, ask(L, R, lson));
    if (R > mid) ans = max(ans, ask(L, R, rson));
    return ans;
}

int gao(int x, int y)
{
    int ans = -1;
    int f1 = top[x]; int f2 = top[y];
    while (f1 != f2){
        if (deep[f1] < deep[f2]){
            swap(f1, f2);
            swap(x, y);
        }
        ans = max(ans, ask(pos[f1], pos[x], 1, z, 1));
        x = father[f1]; f1 = top[x];
    }
    if (x == y) return ans;
    if (deep[x]>deep[y]) swap(x, y);
    ans = max(ans ,ask(pos[son[x]],pos[y],1,z,1));
    return ans;
}


int main()
{
    char str[100];
    int Icase;
    int n;
    cin >> Icase;
    while (Icase--){
        cin >> n;
        memset(size,0,sizeof(size));
        memset(Max,0,sizeof(Max));
        z = 0; len = 0;
        memset(head, -1, sizeof(head));
        for (int i = 1; i < n; i++){
            scanf("%d%d%d", &edge[i][0], &edge[i][1], &edge[i][2]);
            add(edge[i][0], edge[i][1], edge[i][2]);
            add(edge[i][1], edge[i][0], edge[i][2]);
        }
        init(1);
        dfs(1, 1);
        for (int i = 1; i < n ; i++){
            int a = edge[i][0]; int b = edge[i][1]; int c = edge[i][2];
            if (deep[a]>deep[b]) swap(edge[i][0], edge[i][1]);
            update(pos[edge[i][1]], c, 1, z, 1);
        }
        while (scanf("%s", str) != EOF){
            if (str[0] == 'D') break;
            int a; int b;
            scanf("%d%d", &a, &b);
            if (str[0] == 'C'){
                update(pos[edge[a][1]], b, 1, z, 1);
            }
            else {
                printf("%d\n", gao(a, b));
            }
        }
    }
    return 0;
}

 

posted on 2014-10-25 16:43  一个西瓜  阅读(137)  评论(0编辑  收藏  举报

导航