poj3237(树链剖分—边权)

又写了一遍poj3237,回顾了一下树链剖分思想。

在我看来是精简了很多代码,但是代码行数不减反增。

#include
#include
#include
#include 
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define maxn 100005
#define maxm 100005
#define rd(x) scanf("%d", &x)
#define rd2(x, y) scanf("%d%d", &x, &y)
/*poj 3237
对树有三种操作:
Q~  a b  询问a~b路径的最大值;
N~  a b  对a~b路径上的数进行取反操作;(a=-a)
C~  a b  将第a条边的值改为b;
对于取反操作,记录区间的最大和最小值和标记k,更新线段即可。
*/
struct Edge{
    int to, next, v, index;
}edge[maxm*2];
int head[maxn],tot,pos, n;
int top[maxn]; //v所在重链的顶端节点
int fa[maxn],deep[maxn]; //父节点、深度
int num[maxn]; //表示以v为根的子树的节点数
int p[maxn]; //v与其父亲节点的连边在线段树中的位置
int fp[maxn]; //第i条边在线段树中的位置
int son[maxn]; //重儿子
int maxx(int a,int b){return a>b?a:b;}
int mixx(int a,int b){return a> 1;
    if(ky <= mid) update(i << 1, l, mid, ky, v);
    else update((i << 1) | 1, mid + 1, r, ky ,v);
    push_up(i);
}

void change(int i, int l, int r, int lx, int rx){
    if(k[i] && l != r) push_down(i);
    if(l == lx && r == rx){
        k[i] ^= 1;
        ma[i] = - ma[i];
        mi[i] = - mi[i];
        swap(ma[i], mi[i]);
        return ;
    }
    int mid = (l + r) >> 1;
    if(mid >= rx) change(i << 1, l, mid, lx, rx);
    else if(mid < lx) change((i << 1) | 1, mid + 1, r, lx, rx);
    else{
        change(i << 1, l, mid, lx, mid);
        change((i << 1) | 1, mid + 1, r, mid + 1, rx);
    }
    push_up(i);
}
int query(int i, int l, int r, int lx, int rx){
    if(k[i] && l != r) push_down(i);
    if(l == lx && r == rx) return ma[i];
    int mid = (l + r) >> 1;
    if(mid >= rx) return query(i << 1, l, mid, lx, rx);
    else if(mid < lx) return query((i << 1) | 1, mid + 1, r, lx, rx);
    else{
        int lv = query(i << 1, l, mid, lx, mid);
        int rv = query((i << 1) | 1, mid + 1, r, mid + 1, rx);
        return maxx(lv, rv);
    }
}
void addedge(int u, int v, int val, int i){
    edge[tot].to = v;
    edge[tot].next = head[u];
    edge[tot].v = val;
    edge[tot].index = i;
    head[u] = tot++;
}
//第一遍dfs求fa,deep,num,son
void dfs1(int u,int pre, int d){
    deep[u] = d;
    fa[u] = pre;
    num[u] = 1;
    for(int i = head[u]; i != -1; i = edge[i].next){
        int v = edge[i].to;
        if(v != pre){
            dfs1(v, u, d + 1);
            num[u] += num[v];
            if(son[u] == -1 || num[v] > num[son[u]]) son[u] = v;
        }
    }
}
//第二遍dfs求出top和p
void getpos(int u, int sp){
    top[u] = sp;
    p[u] = pos++;
    int cur_pos = pos;
    //fp[p[u]] = u;
    if(son[u] == -1) return;
    getpos(son[u], sp);
    for(int i = head[u]; i != -1; i = edge[i].next){
        int v = edge[i].to;
        int val = edge[i].v;
        int index = edge[i].index;
        if(v != son[u] && v != fa[u]){
            update(1, 1, n - 1, pos, val);
            fp[index] = pos;
            getpos(v,v);
        }
        else if(v == son[u]){
            update(1, 1, n - 1, cur_pos, val);
            fp[index] = cur_pos;
        }
    }
}
//最大值
int findma(int u, int v){
    int f1 = top[u], f2 = top[v];
    int tmp = -1000000000;
    while(f1 != f2){
        if(deep[f1] < deep[f2]){
            swap(f1, f2);
            swap(u, v);
        }
        tmp = maxx(tmp, query(1, 1, n - 1, p[f1], p[u]));
        u = fa[f1];
        f1 = top[u];
    }
    if(u == v) return tmp;
    if(deep[u] > deep[v]) swap(u, v);
    return maxx(tmp, query(1, 1, n - 1, p[son[u]], p[v]));
}
//取反
void change(int u, int v){
    int f1 = top[u], f2 = top[v];
    while(f1 != f2){
        if(deep[f1] < deep[f2]){
            swap(f1, f2);
            swap(u, v);
        }
        change(1, 1, n - 1, p[f1], p[u]);
        u = fa[f1];
        f1 = top[u];
    }
    if(u == v) return;
    if(deep[u] > deep[v]) swap(u, v);
    change(1, 1, n - 1, p[son[u]], p[v]);
}

void build(int i, int l ,int r){
    if(l == r) return ;
    int mid = (l + r) >> 1;
    build(i << 1, l, mid);
    build((i << 1) | 1, mid + 1, r);
}

int main()
{
    int t, a, b, c;
    rd(t);
    while(t--){
        init();
        rd(n);
        for(int i = 1; i < n; i++){
            scanf("%d%d%d", &a, &b, &c);
            addedge(a, b, c, i);
            addedge(b, a, c, i);
        }
        dfs1(1, 0, 0);
        getpos(1, 1);

        char op[10];
        while(scanf("%s", op)){
            if(op[0] == 'D') break;
            scanf("%d%d", &a, &b);
            if(op[0] == 'Q') printf("%d\n", findma(a, b));
            else if(op[0] == 'N') change(a, b);
            else update(1, 1, n - 1, fp[a], b);
        }
    }
    return 0;
}


你可能感兴趣的:(树链剖分)