POJ 3237 - Tree(树链剖分)

来源:互联网 发布:仿商城html5源码 编辑:程序博客网 时间:2024/04/29 16:47

题目:

http://poj.org/problem?id=3237

题意:

给出有边权的一棵树,三个操作:

1.修改边权。

2.将u->v 的路径边权取反。

3.输出u->v 路径的最大边权。

AC.

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int inf = 0x3f3f3f3f;const int maxn = 1e5+5;int deep[maxn], top[maxn], fa[maxn], num[maxn], p[maxn], fp[maxn], son[maxn];int pos;int tot, head[maxn];struct Edge{    int to, next;}edge[maxn*2];void init(){    tot = 0;    memset(head, -1, sizeof(head));    pos = 0;    memset(son, -1, sizeof(son));}void addedge(int u, int v){    edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++;}void dfs1(int u, int pre, int d){    deep[u] = d;    fa[u] = pre;    num[u] = 1;    for(int i = head[u]; ~i; 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;            }        }    }}void getpos(int u, int sp){    top[u] = sp;    p[u] = pos++;    fp[p[u]] = u;    if(son[u] == -1) return;    getpos(son[u], sp);    for(int i = head[u]; ~i; i = edge[i].next) {        int v = edge[i].to;        if(v != son[u] && v != fa[u]) {            getpos(v, v);        }    }}struct Node{    int l, r;    int Max, Min, ne;}segtree[maxn*3];void build(int i, int l, int r){    segtree[i].l = l;    segtree[i].r = r;    segtree[i].Max = 0;    segtree[i].Min = 0;    segtree[i].ne = 0;    if(l == r) return;    int mid = (l+r)/2;    build(i<<1, l, mid);    build((i<<1)|1, mid+1, r);}void push_up(int i){    segtree[i].Max = max(segtree[i<<1].Max, segtree[(i<<1)|1].Max);    segtree[i].Min = min(segtree[i<<1].Min, segtree[(i<<1)|1].Min);}void push_down(int i){    if(segtree[i].l == segtree[i].r) return;    if(segtree[i].ne) {        segtree[i<<1].Max = -segtree[i<<1].Max;        segtree[i<<1].Min = -segtree[i<<1].Min;        swap(segtree[i<<1].Min, segtree[i<<1].Max);        segtree[(i<<1)|1].Max = -segtree[(i<<1)|1].Max;        segtree[(i<<1)|1].Min = -segtree[(i<<1)|1].Min;        swap(segtree[(i<<1)|1].Max, segtree[(i<<1)|1].Min);        segtree[i<<1].ne ^= 1;        segtree[(i<<1)|1].ne ^= 1;        segtree[i].ne = 0;    }}void update(int i, int k, int val){    if(segtree[i].l == k && segtree[i].r == k) {        segtree[i].Max = val;        segtree[i].Min = val;        segtree[i].ne = 0;        return;    }    push_down(i);    int mid = (segtree[i].l + segtree[i].r)/2;    if(k <= mid) update(i<<1, k, val);    else update((i<<1)|1, k, val);    push_up(i);}void ne_update(int i, int l, int r){    if(segtree[i].l == l && segtree[i].r == r) {        segtree[i].Max = -segtree[i].Max;        segtree[i].Min = -segtree[i].Min;        swap(segtree[i].Max, segtree[i].Min);        segtree[i].ne ^= 1;        return;    }    push_down(i);    int mid = (segtree[i].l + segtree[i].r) / 2;    if(r <= mid) ne_update(i<<1, l, r);    else if(l > mid) ne_update((i<<1)|1, l, r);    else {        ne_update(i<<1, l, mid);        ne_update((i<<1)|1, mid+1, r);    }    push_up(i);}int query(int i, int l, int r){    if(segtree[i].l == l && segtree[i].r == r)        return segtree[i].Max;    push_down(i);    int mid = (segtree[i].l + segtree[i].r)/2;    if(r <= mid) return query(i<<1, l, r);    else if(l > mid) return query((i<<1)|1, l, r);    else return max(query(i<<1, l, mid), query((i<<1)|1, mid+1, r));    push_up(i);}int find(int u, int v){    int f1 = top[u], f2 = top[v];    int tmp = -inf;    while(f1 != f2) {        if(deep[f1] < deep[f2]) {            swap(f1, f2);            swap(u, v);        }        tmp = max(tmp, query(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 max(tmp, query(1, p[son[u]], p[v]));}void ne_find(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);        }        ne_update(1, p[f1], p[u]);        u = fa[f1]; f1 = top[u];    }    if(u == v) return ;    if(deep[u] > deep[v]) swap(u, v);    ne_update(1, p[son[u]], p[v]);}int e[maxn][3];int main(){    //freopen("in", "r", stdin);    int T;    scanf("%d", &T);    while(T--) {        int n;        scanf("%d", &n);        init();        for(int i = 0; i < n-1; ++i) {            int u, v, w;            scanf("%d%d%d", &e[i][0], &e[i][1], &e[i][2]);            addedge(e[i][0], e[i][1]);            addedge(e[i][1], e[i][0]);        }        dfs1(1, 0, 0);        getpos(1, 1);        build(1, 0, pos-1);        for(int i = 0; i < n-1; ++i) {            if(deep[e[i][0]] > deep[e[i][1]]) swap(e[i][0], e[i][1]);            update(1, p[e[i][1]], e[i][2]);        }        char q[10];        while(~scanf("%s", q)) {            if(q[0] == 'D') break;            int u, v;            scanf("%d %d", &u, &v);            if(q[0] == 'Q') {                printf("%d\n", find(u, v));            }            if(q[0] == 'C') {                update(1, p[e[u-1][1]], v);            }            if(q[0] == 'N') {                ne_find(u, v);            }        }    }    return 0;}



0 0
原创粉丝点击