POJ 3237 Tree(树链剖分)
来源:互联网 发布:淘宝口碑客服电话 编辑:程序博客网 时间:2024/05/16 07:19
题目链接:点击打开链接
思路:
对于树上的路径更新操作, 我们通常把他hash到线段上, 也就是树链剖分, 大概完全理解了吧, 存个代码。
对于该题的反转操作, 可以里用异或操作的性质来做标记。
细节参见代码:
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <string>#include <vector>#include <stack>#include <ctime>#include <bitset>#include <cstdlib>#include <cmath>#include <set>#include <list>#include <deque>#include <map>#include <queue>#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;typedef long long ll;typedef long double ld;const double eps = 1e-6;const double PI = acos(-1);const int mod = 1000000000 + 7;const int INF = 0x3f3f3f3f;const int seed = 131;const ll INF64 = ll(1e18);const int maxn = 10000 + 10;int T,n,m,tree_id = 0,minv[maxn<<2],maxv[maxn<<2], setv[maxn<<2],val[maxn];struct node { int u, d; node(int u=0, int d=0):u(u),d(d) {}};vector<node> g[maxn];int pre[maxn]; /// x的父亲int siz[maxn]; /// x的子树规模int son[maxn]; /// x的重儿子int dep[maxn]; /// x相对于根结点的深度void dfs(int u, int fa) { siz[u] = 1; pre[u] = fa ; dep[u] = dep[fa] + 1; son[u] = 0; int len = g[u].size(), maxv = 0; for(int i = 0; i < len; i++) { int v = g[u][i].u; if(v == fa) continue; dfs(v, u); siz[u] += siz[v]; if(siz[v] > maxv) { maxv = siz[v]; son[u] = v; } }}int top[maxn]; /// 这条重链的头部int pos[maxn]; /// x重标号后的标号/// tree_idx 用以给所有边重标号void build_tree(int u, int top_id) { top[u] = top_id; pos[u] = ++tree_id; if(son[u]) build_tree(son[u], top_id); int len = g[u].size(); for(int i = 0; i < len; i++) { int v = g[u][i].u; if(v == pre[u]) continue; if(v != son[u]) { build_tree(v, v); } }}void pushup(int o) { minv[o] = min(minv[o<<1], minv[o<<1|1]); maxv[o] = max(maxv[o<<1], maxv[o<<1|1]);}void pushdown(int l, int r, int o) { if(l == r) return ; if(setv[o]) { setv[o] ^= 1; setv[o<<1] ^= 1; int t = minv[o<<1]; minv[o<<1] = -maxv[o<<1]; maxv[o<<1] = -t; setv[o<<1|1] ^= 1; t = minv[o<<1|1]; minv[o<<1|1] = -maxv[o<<1|1]; maxv[o<<1|1] = -t; }}void build(int l, int r, int o) { minv[o] = INF; maxv[o] = -INF; setv[o] = 0; if(l == r) { minv[o] = maxv[o] = val[l]; return ; } int mid = (l + r) >> 1; build(l, mid, o<<1); build(mid+1, r, o<<1|1); pushup(o);}void update(int L, int R, int v, int l, int r, int o) { if(L <= l && r <= R) { if(v == INF) { setv[o] ^= 1; int t = minv[o]; minv[o] = -maxv[o]; maxv[o] = -t; } else { minv[o] = maxv[o] = v; setv[o] = 0; } return ; } pushdown(l, r, o); int mid = (l + r) >> 1; if(L <= mid) update(L, R, v, l, mid, o<<1); if(mid < R) update(L, R, v, mid+1, r, o<<1|1); pushup(o);}int query(int L, int R, int l, int r, int o) { if(L <= l && r <= R) { return maxv[o]; } int mid = (l + r) >> 1; int ans = -INF; pushdown(l, r, o); if(L <= mid) ans = max(ans, query(L, R, l, mid, o<<1)); if(mid < R) ans = max(ans, query(L, R, mid+1, r, o<<1|1)); pushup(o); return ans;}int solve(int x, int y) { int res = -INF; while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x, y); res = max(res, query(pos[top[x]], pos[x], 1, n, 1)); x = pre[top[x]]; } if(x == y) return res; if(dep[x] > dep[y]) swap(x, y); return max(res, query(pos[x]+1, pos[y], 1, n, 1));}void NEGATE(int x, int y) { while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x, y); update(pos[top[x]], pos[x], INF, 1, n, 1); x = pre[top[x]]; } if(x == y) return ; if(dep[x] > dep[y]) swap(x, y); update(pos[x]+1, pos[y], INF, 1, n, 1);}void init() { tree_id = 0; for(int i = 1; i <= n; i++) g[i].clear();}struct edge { int a, b, c;}e[maxn];int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &n); init(); for(int i = 1; i < n; i++) { scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].c); g[e[i].a].push_back(node(e[i].b, e[i].c)); g[e[i].b].push_back(node(e[i].a, e[i].c)); } dfs(1, 0); build_tree(1, 1); for(int i = 1; i < n; i++) { int a = e[i].a, b = e[i].b; if(dep[a] < dep[b]) swap(a, b); val[pos[a]] = e[i].c; } build(1, n, 1); while(true) { char op[10]; scanf("%s", op); int a, b; if(op[0] != 'D') scanf("%d%d", &a, &b); if(op[0] == 'D') break; else if(op[0] == 'Q') { printf("%d\n", solve(a, b)); } else if(op[0] == 'C') { int x = e[a].a, y = e[a].b; if(dep[x] < dep[y]) swap(x, y); update(pos[x], pos[x], b, 1, n, 1); } else { NEGATE(a, b); } } } return 0;}
0 0
- 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 树链剖分
- 二维数组 矩阵相乘
- F
- 安装laravel需要的目录权限
- OSSempend();OSSemPost();函数的解析
- opencv在图片指定区域内填充矩形,并在图片中显示矩形的轮廓
- POJ 3237 Tree(树链剖分)
- 【Java Tip】(三) Object类wait()与nofity()
- Linux初学备忘
- 方程的解数(dfs优化)
- 154. Find Minimum in Rotated Sorted Array II--Array--LeetCode--C++
- hdu1175(DFS)
- python使用requests包爬取Pixiv图片--关注画师的所有作品
- Tribon的网络版(TriWeb)上线啦
- 测试一下