POJ 3237 Tree (树链剖分)
2017-02-28 22:23
459 查看
题意:有一棵n个节点的树,现有以下三种操作:
1、修改第i条边的权值
2、将a到b的路径的权值取反
3、查询a到b路径上的最大权值
思路:典型的树链剖分,路径上的权值用线段树维护,用lazy标记,判断某个区间取反的次数,写个线段树的模板错了大半天,无语......
1、修改第i条边的权值
2、将a到b的路径的权值取反
3、查询a到b路径上的最大权值
思路:典型的树链剖分,路径上的权值用线段树维护,用lazy标记,判断某个区间取反的次数,写个线段树的模板错了大半天,无语......
#include<cstdio> #include<cstring> #include<vector> #include<algorithm> const int maxn = 1e5 + 100; const int INF = 1e9; using namespace std; struct P { int to, w, num; P() {} P(int t, int w, int n) : to(t), w(w), num(n) {} }; struct seg { int l, r, Max, Min; int ls, rs, flag; } C[4 * maxn]; vector<P> G[maxn]; ///存储邻接边信息 int n, tree[maxn], nodecnt; ///重路径划分 int path_cnt, path_size[maxn]; ///重路径数量,路径大小 int fa[maxn], path_top[maxn]; ///父节点,路径顶点 int path_dep[maxn], sz[maxn]; ///路径深度,子树节点数量 int bot[maxn], bel[maxn]; ///有向边指向的节点,节点属于的重路径 int rk[maxn], w[maxn]; ///每个节点是第几个节点,边的权值 int T, x, y, a, b, c; char cmd[10]; void init() { for(int i = 0; i < maxn; i++) { G[i].clear(); nodecnt = 0; fa[i] = path_size[i] = sz[i] = 0; rk[i] = path_dep[i] = tree[i] = 0; } } void add(int f, int t, int we, int num) { G[f].push_back(P(t, we, num)); G[t].push_back(P(f, we, num)); w[num] = we; } void dfs(int k, int dep) { sz[k] = 1; bel[k] = 0; int maxson = 0, j; for(int i = 0; i < G[k].size(); i++) { P p = G[k][i]; if(p.to == fa[k]) continue; fa[p.to] = k; bot[p.num] = p.to; dfs(p.to, dep + 1); sz[k] += sz[p.to]; if(sz[p.to] > maxson) { maxson = sz[p.to]; j = i; } } for(int i = 0; i < G[k].size(); i++) { P p = G[k][i]; if(p.to == fa[k]) continue; if(i == j) { bel[k] = bel[p.to]; rk[k] = rk[p.to] + 1; } else { int t = bel[p.to]; path_dep[t] = dep + 1; path_size[t] = rk[p.to]; path_top[t] = p.to; } } if(!bel[k]) { bel[k] = ++path_cnt; rk[k] = 1; } } void build(int node, int l, int r) { C[node].l = l; C[node].r = r; C[node].Max = -INF; C[node].Min = INF; C[node].flag = 0; if(r - l > 1) { C[node].ls = ++nodecnt; int mid = (l + r) >> 1; build(C[node].ls, l, mid); C[node].rs = ++nodecnt; build(C[node].rs, mid, r); } } void upnode(int o) { int c = C[o].Max; C[o].Max = -C[o].Min; C[o].Min = -c; } void pushdown(int o) { if(!C[o].flag) return ; int ls = C[o].ls, rs = C[o].rs; C[ls].flag += C[o].flag; C[rs].flag += C[o].flag; if(C[o].flag & 1) { upnode(ls); upnode(rs); } C[o].flag = 0; } void pushup(int o) { int ls = C[o].ls, rs = C[o].rs; int lag = C[ls].flag; int rag = C[rs].flag; C[o].Max = max(C[ls].Max, C[rs].Max); C[o].Min = min(C[ls].Min, C[rs].Min); } void change(int o, int ind, int data) { if(C[o].r - C[o].l == 1) { C[o].Max = C[o].Min = data; C[o].flag = 0; 4000 return ; } int mid = (C[o].l + C[o].r) >> 1; pushdown(o); if(ind < mid) change(C[o].ls, ind, data); else change(C[o].rs, ind, data); pushup(o); } void change2(int o, int l, int r) { if(C[o].l >= l && C[o].r <= r) { C[o].flag++; upnode(o); return ; } if(C[o].r <= l || C[o].l >= r) return ; int mid = (C[o].l + C[o].r) >> 1; pushdown(o); if(mid > l) change2(C[o].ls, l, r); if(mid <= r) change2(C[o].rs, l, r); pushup(o); } void update(int a, int b) { int x = bel[a], y = bel[b]; while(x != y) { if(path_dep[x] > path_dep[y]) { change2(tree[x], rk[a], path_size[x] + 1); a = fa[path_top[x]]; x = bel[a]; } else { change2(tree[y], rk[b], path_size[y] + 1); b = fa[path_top[y]]; y = bel[b]; } } if(rk[a] == rk[b]) return ; int ra = rk[a], rb = rk[b]; if(ra > rb) change2(tree[x], rb, ra); else change2(tree[x], ra, rb); } int ask(int o, int l, int r) { if(C[o].l >= l && C[o].r <= r) return C[o].Max; if(C[o].l >= r || C[o].r <= l) return -INF; pushdown(o); int p1 = ask(C[o].ls, l, r); int p2 = ask(C[o].rs, l, r); return max(p1, p2); } void work(int x, int y) { change(tree[bel[bot[x]]], rk[bot[x]], y); } void prepare() { dfs(1, 0); int i = bel[1]; path_dep[i] = 0; path_size[i] = rk[1]; path_top[i] = 1; for(i = 1; i <= path_cnt; i++) { tree[i] = ++nodecnt; build(tree[i], 1, path_size[i] + 1); } for(i = 1; i < n; i++) work(i, w[i]); } int query(int a, int b) { int ans = -INF, x = bel[a], y = bel[b], k; while(x != y) { if(path_dep[x] > path_dep[y]) { k = ask(tree[x], rk[a], path_size[x] + 1); ans = max(ans, k); a = fa[path_top[x]]; x = bel[a]; } else { k = ask(tree[y], rk[b], path_size[y] + 1); ans = max(ans, k); b = fa[path_top[y]]; y = bel[b]; } } if(rk[a] == rk[b]) return ans; int ra = rk[a], rb = rk[b]; if(ra > rb) k = ask(tree[x], rb, ra); else k = ask(tree[x], ra, rb); return max(ans, k); } int main() { scanf("%d", &T); while(T--) { init(); scanf("%d", &n); for(int i = 1; i < n; i++) { scanf("%d %d %d", &a, &b, &c); add(a, b, c, i); } prepare(); while(scanf("%s", cmd) && cmd[0] != 'D') { scanf("%d %d", &x, &y); if(cmd[0] == 'C') work(x, y); else if(cmd[0] == 'N') update(x, y); else printf("%d\n", query(x, y)); } } return 0; }
相关文章推荐
- POJ 3237 Tree 树链剖分
- poj 3237 Tree 树链剖分 动态树 LCT
- POJ 3237 Tree 树链剖分
- poj 3237 Tree 树链剖分
- poj 3237 Tree 树链剖分
- poj 3237 Tree(树链剖分,点权,线段树)
- POJ 3237 Tree (树链剖分)
- POJ 3237 Tree 树链剖分
- POJ 3237 Tree(树链剖分-线段树点更新-区间更新-区间最值查询-入边)
- POJ-3237:Tree(树链剖分)
- 【POJ】3237 Tree 树链剖分
- POJ 3237 Tree (树链剖分)
- POJ 3237 Tree 树链剖分
- POJ 3237 Tree(树链剖分模板)
- POJ 3237 - Tree(树链剖分)
- POJ 3237 Tree(树链剖分 + 单点更新 + 区间更新 + 区间查询)
- POJ-3237 Tree(树链剖分)
- POJ 3237 Tree(树链剖分)
- 【树链剖分】 POJ 3237 Tree
- poj 3237 Tree 树链剖分