POJ 3237 Tree

Tree

Time Limit: 5000MS Memory Limit: 131072K

Description

You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:

CHANGE i v Change the weight of the ith edge to v
NEGATE a b Negate the weight of every edge on the path from a to b
QUERY a b Find the maximum weight of edges on the path from a to b

Input

The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers a, b and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.

Output

For each “QUERY” instruction, output the result on a separate line.

Sample Input

1

3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE

Sample Output

1
3

题意:

有一个n个节点的树,然后根据题目所给出的查询条件,去查询最大权值,取反,更改边对应的区间中点的权值。

思路:

看到更改边来改变点的权值就可以想到是树链剖分,然后用线段树去维护,但是再维护的时候取反中,最大值要和最小值互换,因为变成了负数了,然后线段树的lazy标记为什么要判断lazy & 1而不是lazy是否存在,因为取反两次之后相当于不用取反。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 10010;
const int inf = 0x7fffffff;
struct Edge {
    int to;
    int next;
};
Edge edge[maxn << 1];
int num[maxn];
int top[maxn];
int deep[maxn];
int fa[maxn];
int p[maxn];
int fp[maxn];
int head[maxn];
int son[maxn];
int tot, pos;
void init() {
    tot = 0;
    pos = 0;
    memset(head, -1, sizeof(head));
    memset(son, -1, sizeof(son));
}
void addedge(int u, int v) {
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
void dfs(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) {
            dfs(v, u, d + 1);
            num[u] += num[v];
            if (son[u] == -1 || num[son[u]] < num[v]) {
                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 != -1; i = edge[i].next) {
        int v = edge[i].to;
        if (v != fa[u] && v != son[u]) {
            getpos(v, v);
        }
    }
}
struct NODE {
    int l;
    int r;
    int Max;
    int Min;
    int lazy;
    int mid () {
        return (l + r) >> 1;
    }
};
NODE node[maxn << 2];
void pushup(int rt) {
    node[rt].Max = max(node[rt << 1].Max, node[rt << 1 | 1].Max);
    node[rt].Min = min(node[rt << 1].Min, node[rt << 1 | 1].Min);
}
void pushdown(int rt) {
    if (node[rt].lazy & 1) {
        node[rt << 1].lazy += node[rt].lazy;
        node[rt << 1 | 1].lazy += node[rt].lazy;
        node[rt << 1].Max = -node[rt << 1].Max;
        node[rt << 1].Min = -node[rt << 1].Min;
        swap(node[rt << 1].Max, node[rt << 1].Min);
        node[rt << 1 | 1].Max = -node[rt << 1 | 1].Max;
        node[rt << 1 | 1].Min = -node[rt << 1 | 1].Min;
        swap(node[rt << 1 | 1].Max, node[rt << 1 | 1].Min);
        node[rt].lazy = 0;
    }
}
void build(int l, int r, int rt) {
    node[rt].l = l;
    node[rt].r = r;
    node[rt].Min = inf;
    node[rt].Max = -inf;
    node[rt].lazy = 0;
    if (l == r) return ;
    int mid = node[rt].mid();
    build(l, mid, rt << 1);
    build(mid + 1, r, rt << 1 | 1);
    pushup(rt);
}
void updata(int l, int r, int rt) {
    if (node[rt].l == l && node[rt].r == r) {
        node[rt].Max = -node[rt].Max;
        node[rt].Min = -node[rt].Min;
        swap(node[rt].Max, node[rt].Min);
        node[rt].lazy++;
        return ;
    }
    pushdown(rt);
    int mid = node[rt].mid();
    if (r <= mid) updata(l, r, rt << 1);
    else if (l > mid) updata(l, r, rt << 1 | 1);
    else {
        updata(l, mid, rt << 1);
        updata(mid + 1, r, rt << 1 | 1);
    }
    pushup(rt);
}
void reupdata(int u, int v) {
    int f1 = top[u], f2 = top[v];
    while (f1 != f2) {
        if (deep[f1] < deep[f2]) {
            swap(u, v);
            swap(f1, f2);
        }
        updata(p[f1], p[u], 1);
        u = fa[f1];
        f1 = top[u];
    }
    if (v == u) return ;
    if (deep[u] > deep[v]) swap(u, v);
    updata(p[son[u]], p[v], 1);
}
int query(int l, int r, int rt) {
    if (node[rt].l == l && node[rt].r == r) {
          return node[rt].Max;
    }
    pushdown(rt);
    int mid = node[rt].mid();
    int res = -inf;
    if (r <= mid) res = max(res, query(l, r, rt << 1));
    else if (l > mid) res = max(res, query(l, r, rt << 1 | 1));
    else {
        res = max(res, query(l, mid, rt << 1));
        res = max(res, query(mid + 1, r, rt << 1 | 1));
    }
    pushup(rt);
    return res;
}
void updataedge(int k, int val, int rt) {
    if (node[rt].l == k && node[rt].r == k) {
        node[rt].Max = node[rt].Min = val;
        return ;
    }
    pushdown(rt);
    int mid = node[rt].mid();
    if (k <= mid) updataedge(k, val, rt << 1);
    else updataedge(k, val, rt << 1 | 1);
    pushup(rt);
}
int findn(int u, int v) {
    int f1 = top[u], f2 = top[v], tmp = -inf;
    while (f1 != f2) {
        if (deep[f1] < deep[f2]) {
            swap(f1, f2);
            swap(u, v);
        }
        tmp = max(tmp, query(p[f1], p[u], 1));
        u = fa[f1];
        f1 = top[u];
    }

    if (v == u) return tmp;
    if (deep[u] > deep[v]) swap(u, v);
    tmp = max(tmp, query(p[son[u]], p[v], 1));
    return tmp;
}
int e[maxn][3];
int main() {
	int t, u, v, val, n;
	scanf("%d", &t);
	while (t--) {
		init();
		scanf("%d", &n);
		for (int i = 1; i <= n - 1; i++) {
			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]);
		}
		dfs(1, 0, 1);
		getpos(1, 1);
        build(1, pos, 1);
		for (int i = 1; i <= n - 1; i++) {
            if (deep[e[i][0]] > deep[e[i][1]]) swap(e[i][0], e[i][1]);
			updataedge(p[e[i][1]], e[i][2], 1);
		}
		char s[10];
		int a, b;
		while (scanf("%s", s) != EOF && s[0] != 'D') {
			scanf("%d %d", &a, &b);
 			if (s[0] == 'Q') printf("%d\n", findn(a, b));
			else if (s[0] == 'C') updataedge(p[e[a][1]], b, 1);
			else reupdata(a, b);
		}
	}
	return 0;
}
/*
1
15
7 1 93
6 2 41
6 1 48
14 4 62
12 15 43
7 8 2
2 10 80
7 13 92
13 5 91
13 11 5
15 1 79
2 3 21
9 12 7
15 4 33
Q 13 7
C 6 6
N 13 1
Q 3 15
C 12 11
N 14 11
Q 2 11
N 2 7
Q 6 7
C 11 10
N 3 8
Q 14 8
C 3 4
Q 8 13
C 5 1
N 7 1
Q 1 11
C 11 8
DONE
*/
/*
92
79
93
-48
93
92
92
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值