POJ_2763
用link-cut-tree或者树链剖分都可以,只要支持单点修改和区间求和就可以了。但后面看dicuss里面说是树状数组和LCA,但由于这两个东西我暂时都没研究过,所以就没再深究这种解法了。
#include<stdio.h> #include<string.h> #define MAXD 100010 #define MAXM 200010 int N, Q, S, first[MAXD], e, next[MAXM], v[MAXM], w[MAXM], q[MAXD], dep[MAXD]; struct Edge { int x, y, z; }edge[MAXD]; struct Splay { int pre, ls, rs, sum, key; bool root; void update(); void zig(int ); void zag(int ); void splay(int ); void renew() { root = true; pre = ls = rs = 0; } }sp[MAXD]; void Splay::update() { sum = sp[ls].sum + sp[rs].sum + key; } void Splay::zig(int x) { int y = rs, fa = pre; 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; 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(; !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 Swap(int &x, int &y) { int t; t = x, x = y, y = t; } void prepare() { int i, j, x, rear = 0; sp[0].sum = 0; 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, sp[v[j]].key = sp[v[j]].sum = w[j], dep[v[j]] = dep[x] + 1; q[rear ++] = v[j]; } } } void add(int x, int y, int z) { v[e] = y, w[e] = z; next[e] = first[x], first[x] = e ++; } void init() { int i; memset(first, -1, sizeof(first)); e = 0; 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 Query(int x) { int fx; access(S); S = x; for(fx = x, x = 0; fx != 0; x = fx, fx = sp[x].pre) { sp[fx].splay(fx); if(sp[fx].pre == 0) printf("%d\n", sp[sp[fx].rs].sum + sp[x].sum); sp[sp[fx].rs].root = true; sp[fx].rs = x, sp[x].root = false; sp[fx].update(); } } void Change(int x, int v) { sp[x].splay(x); sp[x].key = v; sp[x].update(); } void solve() { int i, x, y, op; for(i = 0; i < Q; i ++) { scanf("%d%d", &op, &x); if(op == 0) Query(x); else { scanf("%d", &y); Change(edge[x].y, y); } } } int main() { while(scanf("%d%d%d", &N, &Q, &S) == 3) { init(); solve(); } return 0; }