POJ_3237
用link-cut-tree或者树链剖分都可以,为了处理negate操作,出了lazy标记外可以做两个标记max、min,在执行negate时,令max=-min、min=-max即可。
#include<stdio.h> #include<string.h> #define MAXD 100010 #define MAXM 200010 #define INF 0x7fffffff int N, q[MAXD], first[MAXD], e, next[MAXM], v[MAXM], w[MAXM], dep[MAXD]; struct Edge { int x, y, z; }edge[MAXD]; struct Splay { int pre, ls, rs, neg, key, max, min; bool root; void update(); void pushdown(); void zig(int ); void zag(int ); void splay(int ); void renew() { root = true; pre = ls = rs = 0; neg = 0; } }sp[MAXD]; int Max(int x, int y) { return x > y ? x : y; } int Min(int x, int y) { return x < y ? x : y; } void Splay::update() { max = Max(Max(sp[ls].max, sp[rs].max), key); min = Min(Min(sp[ls].min, sp[rs].min), key); } void makeneg(int cur) { if(cur != 0) { sp[cur].neg ^= 1, sp[cur].key = -sp[cur].key; int t = sp[cur].max; sp[cur].max = -sp[cur].min, sp[cur].min = -t; } } void Splay::pushdown() { if(neg) { makeneg(ls), makeneg(rs); neg = 0; } } void Splay::zig(int x) { int y = rs, fa = pre; pushdown(), sp[y].pushdown(); rs = sp[y].ls, sp[rs].pre = x; sp[y].ls = x, pre = y; sp[y].pre = fa; if(root) root = false, sp[y].root = true; else sp[fa].rs == x ? sp[fa].rs = y : sp[fa].ls = y; update(); } void Splay::zag(int x) { int y = ls, fa = pre; pushdown(), sp[y].pushdown(); ls = sp[y].rs, sp[ls].pre = x; sp[y].rs = x, pre = y; sp[y].pre = fa; if(root) root = false, sp[y].root = true; else sp[fa].rs == x ? sp[fa].rs = y : sp[fa].ls = y; update(); } void Splay::splay(int x) { int y, z; for(pushdown(); !root;) { y = pre; if(sp[y].root) sp[y].rs == x ? sp[y].zig(y) : sp[y].zag(y); else { z = sp[y].pre; if(sp[z].rs == y) { if(sp[y].rs == x) sp[z].zig(z), sp[y].zig(y); else sp[y].zag(y), sp[z].zig(z); } else { if(sp[y].ls == x) sp[z].zag(z), sp[y].zag(y); else sp[y].zig(y), sp[z].zag(z); } } } update(); } void add(int x, int y, int z) { v[e] = y, w[e] = z; next[e] = first[x], first[x] = e ++; } void prepare() { int i, j, x, rear = 0; sp[0].max = -INF, sp[0].min = INF; q[rear ++] = 1; sp[1].renew(), dep[1] = 1; for(i = 0; i < rear; i ++) { x = q[i]; for(j = first[x]; j != -1; j = next[j]) if(v[j] != sp[x].pre) { sp[v[j]].renew(), sp[v[j]].pre = x, dep[v[j]] = dep[x] + 1; sp[v[j]].key = sp[v[j]].max = sp[v[j]].min = w[j]; q[rear ++] = v[j]; } } } void Swap(int &x, int &y) { int t; t = x, x = y, y = t; } void init() { int i; memset(first, -1, sizeof(first)); e = 0; scanf("%d", &N); for(i = 1; i < N; i ++) { scanf("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].z); add(edge[i].x, edge[i].y, edge[i].z), add(edge[i].y, edge[i].x, edge[i].z); } prepare(); for(i = 1; i < N; i ++) if(dep[edge[i].x] > dep[edge[i].y]) Swap(edge[i].x, edge[i].y); } void access(int x) { int fx; for(fx = x, x = 0; fx != 0; x = fx, fx = sp[x].pre) { sp[fx].splay(fx); sp[sp[fx].rs].root = true; sp[fx].rs = x, sp[x].root = false; sp[fx].update(); } } void Change(int x, int y) { sp[x].splay(x); sp[x].key = y; sp[x].update(); } void Negate(int x, int y) { int fy; access(x); for(fy = y, y = 0; fy != 0; y = fy, fy = sp[y].pre) { sp[fy].splay(fy); if(sp[fy].pre == 0) makeneg(sp[fy].rs), makeneg(y); sp[sp[fy].rs].root = true; sp[fy].rs = y, sp[y].root = false; sp[fy].update(); } } void Query(int x, int y) { int fy; access(x); for(fy = y, y = 0; fy != 0; y = fy, fy = sp[y].pre) { sp[fy].splay(fy); if(sp[fy].pre == 0) printf("%d\n", Max(sp[sp[fy].rs].max, sp[y].max)); sp[sp[fy].rs].root = true; sp[fy].rs = y, sp[y].root = false; sp[fy].update(); } } void solve() { int x, y; char op[10]; for(;;) { scanf("%s", op); if(op[0] == 'D') break; scanf("%d%d", &x, &y); if(op[0] == 'C') Change(edge[x].y, y); else if(op[0] == 'N') Negate(x, y); else Query(x, y); } } int main() { int t; scanf("%d", &t); while(t --) { init(); solve(); } return 0; }
来源:https://www.cnblogs.com/staginner/archive/2012/06/16/2551758.html