POJ - 3237 题解(树链剖分)

题目传送门

题意

给n个点,有n-1条边连起来,每条边有自己的权值,多个操作:改变第i条边的权值;将a到b的链的边的权值取相反数;查询a到b的链上最大的权值。

题解

树链剖分,维护最大最小值,要取相反数的时候,最大最小值交换,再取相反数即可。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>
using namespace std;
const int MAXN = 100005;
int w[MAXN], rk[MAXN];
int n;
struct sgm {
    int l, r;
    long long minn;
    long long maxn;
    int lazy;
    void _swap() {
        swap ( minn, maxn );
        minn = -minn;
        maxn = -maxn;
    }
} sgmt[MAXN << 2];
inline void push_up ( int rt ) {
    sgmt[rt].minn = min ( sgmt[rt << 1].minn, sgmt[rt << 1 | 1].minn );
    sgmt[rt].maxn = max ( sgmt[rt << 1].maxn, sgmt[rt << 1 | 1].maxn );
}
inline void push_down ( int rt ) {
    if ( sgmt[rt].lazy ) {
        sgmt[rt << 1].lazy ^= 1;
        sgmt[rt << 1]._swap();
        sgmt[rt << 1 | 1].lazy ^= 1;
        sgmt[rt << 1 | 1]._swap();
        sgmt[rt].lazy = 0;
    }
}
void build ( int rt, int l, int r ) {
    sgmt[rt].l = l;
    sgmt[rt].r = r;
    sgmt[rt].lazy = 0;
    if ( l == r ) {
        if ( l == 1 ) {
            sgmt[rt].minn = sgmt[rt].maxn = 0;
        } else {
            sgmt[rt].minn = sgmt[rt].maxn = w[l];
        }
        return;
    }
    int mid = ( l + r ) >> 1;
    build ( rt << 1, l, mid );
    build ( rt << 1 | 1, mid + 1, r );
    push_up ( rt );
}
void change ( int rt, int l, int c ) {
    if ( l == sgmt[rt].l && l == sgmt[rt].r ) {
        sgmt[rt].minn = sgmt[rt].maxn = c;
        sgmt[rt].lazy = 0;
        return;
    }
    push_down ( rt );
    int mid = ( sgmt[rt].l + sgmt[rt].r ) >> 1;
    if ( l <= mid ) {
        change ( rt << 1, l, c );
    }
    if ( mid < l ) {
        change ( rt << 1 | 1, l, c );
    }
    push_up ( rt );
}
void update ( int rt, int l, int r ) {
    if ( l <= sgmt[rt].l && sgmt[rt].r <= r ) {
        sgmt[rt]._swap();
        sgmt[rt].lazy ^= 1;
        return;
    }
    push_down ( rt );
    int mid = ( sgmt[rt].l + sgmt[rt].r ) >> 1;
    if ( l <= mid ) {
        update ( rt << 1, l, r );
    }
    if ( mid < r ) {
        update ( rt << 1 | 1, l, r );
    }
    push_up ( rt );
}
long long query ( int rt, int l, int r ) {
    if ( l <= sgmt[rt].l && sgmt[rt].r <= r ) {
        return sgmt[rt].maxn;
    }
    push_down ( rt );
    long long ans = -0x3f3f3f3f;
    int mid = ( sgmt[rt].l + sgmt[rt].r ) >> 1;
    if ( l <= mid ) {
        ans = max ( ans, query ( rt << 1, l, r ) );
    }
    if ( mid < r ) {
        ans = max ( ans, query ( rt << 1 | 1, l, r ) );
    }
    return ans;
}
int Head[MAXN << 1], ver[MAXN << 1], nxt[MAXN << 1];
int E;
void addedge ( int u, int v ) {
    ver[E] = v;
    nxt[E] = Head[u];
    Head[u] = E++;
}
int cnt;
int son[MAXN], size[MAXN], d[MAXN], fa[MAXN], top[MAXN], id[MAXN];
void dfs1 ( int f, int u, int depth ) {
    size[u] = 1;
    son[u] = 0;
    d[u] = depth;
    fa[u] = f;
    for ( int i = Head[u]; ~i; i = nxt[i] ) {
        int v = ver[i];
        if ( v == f ) {
            continue;
        }
        dfs1 ( u, v, depth + 1 );
        size[u] += size[v];
        if ( size[v] > size[son[u]] ) {
            son[u] = v;
        }
    }
}
void dfs2 ( int f, int u ) {
    top[u] = f;
    id[u] = ++cnt;
    rk[cnt] = u;
    if ( !son[u] ) {
        return;
    }
    dfs2 ( f, son[u] );
    for ( int i = Head[u]; ~i; i = nxt[i] ) {
        int v = ver[i];
        if ( v == fa[u] || v == son[u] ) {
            continue;
        }
        dfs2 ( v, v );
    }
}
void pathinv ( int x, int y ) {
    int fx = top[x], fy = top[y];
    while ( id[fx] != id[fy] ) {
        if ( d[fx] > d[fy] ) {
            update ( 1, id[fx], id[x] );
            x = fa[fx];
            fx = top[x];
        } else {
            update ( 1, id[fy], id[y] );
            y = fa[fy];
            fy = top[y];
        }
    }
    if ( id[x] > id[y] ) {
        update ( 1, id[son[y]], id[x] );
    } else if ( id[x] < id[y] ) {
        update ( 1, id[son[x]], id[y] );
    }
    return;
}
long long pathmax ( int x, int y ) {
    long long ans = -0x3f3f3f3f;
    int fx = top[x], fy = top[y];
    if ( x == y ) {
        return 0;
    }
    while ( id[fx] != id[fy] ) {
        if ( d[fx] > d[fy] ) {
            ans = max ( ans, query ( 1, id[fx], id[x] ) );
            x = fa[fx];
            fx = top[x];
        } else {
            ans = max ( ans, query ( 1, id[fy], id[y] ) );
            y = fa[fy];
            fy = top[y];
        }
    }
    if ( id[x] > id[y] ) {
        ans = max ( ans, query ( 1, id[son[y]], id[x] ) );
    } else if ( id[x] < id[y] ) {
        ans = max ( ans, query ( 1, id[son[x]], id[y] ) );
    }
    return ans;
}
struct edge {
    int u, v, w;
    void input() {
        scanf ( "%d%d%d", &u, &v, &w );
        addedge ( u, v );
        addedge ( v, u );
    }
} e[MAXN];
int x, y, k;
char s[10];
int main() {
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    int t;
    scanf ( "%d", &t );
    while ( t-- ) {
        E = 0;
        cnt = 0;
        memset ( Head, -1, sizeof ( Head ) );
        scanf ( "%d", &n );
        for ( int i = 1; i < n; i++ ) {
            e[i].input();
        }
        dfs1 ( 0, 1, 1 );
        dfs2 ( 1, 1 );
        for ( int i = 1; i < n; i++ ) {
            if ( d[e[i].u] > d[e[i].v] ) {
                swap ( e[i].u, e[i].v );
            }
            w[id[e[i].v]] = e[i].w;
        }
        w[1] = 0;
        build ( 1, 1, n );
        while ( ~scanf ( "%s", s ) ) {
            if ( s[0] == 'D' ) {
                break;
            } else if ( s[0] == 'C' ) {
                scanf ( "%d %d", &x, &k );
                change ( 1, id[e[x].v], k );
            } else if ( s[0] == 'N' ) {
                scanf ( "%d %d", &x, &y );
                pathinv ( x, y );
            } else if ( s[0] == 'Q' ) {
                scanf ( "%d %d", &x, &y );
                printf ( "%lld\n", pathmax ( x, y ) );
            }
        }
    }
    return 0;
}

 

全部评论

相关推荐

牛客246576843号:建议简历对点优化,想做HR专门列出HR实习,想做运营专门列出运营实习,并且对点写出项目经历以及数据,同时在个人总结上可以多凸出和岗位的匹配度
点赞 评论 收藏
分享
mjasjon:这种trash中厂 简历过筛概率比大厂还低(除阿里系)
投递哔哩哔哩等公司6个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务