又写了一遍poj3237,回顾了一下树链剖分思想。
在我看来是精简了很多代码,但是代码行数不减反增。
#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define maxn 100005 #define maxm 100005 #define rd(x) scanf("%d", &x) #define rd2(x, y) scanf("%d%d", &x, &y) /*poj 3237 对树有三种操作: Q~ a b 询问a~b路径的最大值; N~ a b 对a~b路径上的数进行取反操作;(a=-a) C~ a b 将第a条边的值改为b; 对于取反操作,记录区间的最大和最小值和标记k,更新线段即可。 */ struct Edge{ int to, next, v, index; }edge[maxm*2]; int head[maxn],tot,pos, n; int top[maxn]; //v所在重链的顶端节点 int fa[maxn],deep[maxn]; //父节点、深度 int num[maxn]; //表示以v为根的子树的节点数 int p[maxn]; //v与其父亲节点的连边在线段树中的位置 int fp[maxn]; //第i条边在线段树中的位置 int son[maxn]; //重儿子 int maxx(int a,int b){return a>b?a:b;} int mixx(int a,int b){return a> 1; if(ky <= mid) update(i << 1, l, mid, ky, v); else update((i << 1) | 1, mid + 1, r, ky ,v); push_up(i); } void change(int i, int l, int r, int lx, int rx){ if(k[i] && l != r) push_down(i); if(l == lx && r == rx){ k[i] ^= 1; ma[i] = - ma[i]; mi[i] = - mi[i]; swap(ma[i], mi[i]); return ; } int mid = (l + r) >> 1; if(mid >= rx) change(i << 1, l, mid, lx, rx); else if(mid < lx) change((i << 1) | 1, mid + 1, r, lx, rx); else{ change(i << 1, l, mid, lx, mid); change((i << 1) | 1, mid + 1, r, mid + 1, rx); } push_up(i); } int query(int i, int l, int r, int lx, int rx){ if(k[i] && l != r) push_down(i); if(l == lx && r == rx) return ma[i]; int mid = (l + r) >> 1; if(mid >= rx) return query(i << 1, l, mid, lx, rx); else if(mid < lx) return query((i << 1) | 1, mid + 1, r, lx, rx); else{ int lv = query(i << 1, l, mid, lx, mid); int rv = query((i << 1) | 1, mid + 1, r, mid + 1, rx); return maxx(lv, rv); } } void addedge(int u, int v, int val, int i){ edge[tot].to = v; edge[tot].next = head[u]; edge[tot].v = val; edge[tot].index = i; head[u] = tot++; } //第一遍dfs求fa,deep,num,son void dfs1(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){ dfs1(v, u, d + 1); num[u] += num[v]; if(son[u] == -1 || num[v] > num[son[u]]) son[u] = v; } } } //第二遍dfs求出top和p void getpos(int u, int sp){ top[u] = sp; p[u] = pos++; int cur_pos = 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; int val = edge[i].v; int index = edge[i].index; if(v != son[u] && v != fa[u]){ update(1, 1, n - 1, pos, val); fp[index] = pos; getpos(v,v); } else if(v == son[u]){ update(1, 1, n - 1, cur_pos, val); fp[index] = cur_pos; } } } //最大值 int findma(int u, int v){ int f1 = top[u], f2 = top[v]; int tmp = -1000000000; while(f1 != f2){ if(deep[f1] < deep[f2]){ swap(f1, f2); swap(u, v); } tmp = maxx(tmp, query(1, 1, n - 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 maxx(tmp, query(1, 1, n - 1, p[son[u]], p[v])); } //取反 void change(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); } change(1, 1, n - 1, p[f1], p[u]); u = fa[f1]; f1 = top[u]; } if(u == v) return; if(deep[u] > deep[v]) swap(u, v); change(1, 1, n - 1, p[son[u]], p[v]); } void build(int i, int l ,int r){ if(l == r) return ; int mid = (l + r) >> 1; build(i << 1, l, mid); build((i << 1) | 1, mid + 1, r); } int main() { int t, a, b, c; rd(t); while(t--){ init(); rd(n); for(int i = 1; i < n; i++){ scanf("%d%d%d", &a, &b, &c); addedge(a, b, c, i); addedge(b, a, c, i); } dfs1(1, 0, 0); getpos(1, 1); char op[10]; while(scanf("%s", op)){ if(op[0] == 'D') break; scanf("%d%d", &a, &b); if(op[0] == 'Q') printf("%d\n", findma(a, b)); else if(op[0] == 'N') change(a, b); else update(1, 1, n - 1, fp[a], b); } } return 0; }