[Preface] ttvtt asked me to WHL and then ...... After 5 rounds of WA, 6 rounds of RE, and 3 rounds of TLE, I finally broke down with this question.
A tree provides an edge weight. There are two operations: change the value of an edge and find the maximum edge weight from path a to path B.
[Click it] This is a good training question for tree link splitting and edge partitioning. However, the data seems abnormal and easy to look like TLE. Actually, I am also in Phuket.
[Idea]: For a tree, each node (except the root node) has only one father. For each edge, the node that is the son is used to record the edge weight. This is generally the case. When TVT is then queried, note that the depth of the first node of the chain is compared with that of the vertex splitting, because the edge splitting is different from that of the vertex splitting, deep points are connected to their parent nodes. Therefore, if we compare the bottom nodes, when we come to the LCA, we will move up to an unnecessary node, an error occurs.
[Conclusion]: map nodes are used to correspond to edges, but TLE is used. Then pre and fun1 are used to correspond to the relations between input vertices and input nodes, use tree and fun2 to correspond to the numbered node and number. That's enough.
The AC code (420 ms ):
[Is the data on Buji island weak? I used it for ms. It seems that some chicory products have used 2.6s _ (: chicory "∠ )_]
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <climits> 5 using namespace std; 6 int const maxn = 10009; 7 int pre[maxn], n, edge, cnt, fa[maxn], deep[maxn], num[maxn], son[maxn], tree[maxn], fun1[maxn], fun2[maxn]; 8 int to[maxn<<1], next[maxn<<1], head[maxn], top[maxn], seq[maxn<<1], cost[maxn]; 9 void add(int u, int v, int num) 10 { 11 to[edge] = v; 12 next[edge] = head[u]; 13 seq[edge] = num; 14 head[u] = edge++; 15 } 16 void init() 17 { 18 scanf("%d", &n); 19 memset(head, -1, sizeof(head)); 20 memset(son, -1, sizeof(son)); 21 edge = cnt = 0; 22 for(int i = 1; i < n; i++) { 23 int a, b; scanf("%d%d%d", &a, &b, &cost[i]); 24 add(a, b, i); add(b, a, i); 25 } 26 fa[1] = deep[1] = tree[1] = 1; 27 } 28 void dfs1(int u) 29 { 30 num[u] = 1; 31 for(int e = head[u]; ~e; e = next[e]) { 32 int too = to[e]; 33 if(fa[u] != too) { 34 pre[seq[e]] = too; //把输入的边和较深的节点对应起来 35 fun1[too] = seq[e]; //存节点对应的边 36 deep[too] = deep[u]+1; 37 fa[too] = u; 38 dfs1(too); num[u] += num[too]; 39 if(son[u] == -1||num[son[u]] < num[too]) son[u] = too; 40 } 41 } 42 } 43 void dfs2(int u, int lead) 44 { 45 top[u] = lead; 46 if(u != 1) tree[u] = ++cnt, fun2[cnt] = u; //剖分的编号一一对应 47 if(son[u] == -1) return; 48 dfs2(son[u], lead); 49 for(int e = head[u]; ~e; e = next[e]) { 50 int too = to[e]; 51 if(fa[u] != too && son[u] != too) dfs2(too, too); 52 } 53 } 54 #define lson l, m, rt<<1 55 #define rson m+1, r, rt<<1|1 56 int sgt[maxn<<2] = {INT_MIN}; 57 void push_up(int rt) 58 { 59 sgt[rt] = max(sgt[rt<<1], sgt[rt<<1|1]); 60 } 61 void build(int l, int r, int rt) 62 { 63 if(l == r) { 64 int pos = fun1[fun2[l]]; 65 sgt[rt] = cost[pos]; return; 66 } 67 int m = (l+r)>>1; 68 build(lson); build(rson); 69 push_up(rt); 70 } 71 void change(int l, int r, int rt, int pos, int val) 72 { 73 if(l == r) { sgt[rt] = val; return; } 74 int m = (l+r)>>1; 75 if(pos <= m) change(lson, pos, val); 76 if(m < pos) change(rson, pos, val); 77 push_up(rt); 78 } 79 int query(int l, int r, int rt, int L, int R) 80 { 81 if(L <= l && r <= R) return sgt[rt]; 82 int m = (l+r)>>1; 83 int a, b; a = b = INT_MIN; 84 if(L <= m) a = query(lson, L, R); 85 if(m < R) b = query(rson, L, R); 86 return max(a, b); 87 } 88 int answer(int a, int b) 89 { 90 if(a == b) return 0; 91 int ans = INT_MIN; 92 while(top[a] != top[b]) { 93 if(deep[top[a]] < deep[top[b]]) swap(a, b); 94 ans = max(ans, query(1, n-1, 1, tree[top[a]], tree[a])); 95 a = fa[top[a]]; 96 } 97 if(deep[a] > deep[b]) swap(a, b); 98 if(a != b) ans = max(ans, query(1, n-1, 1, tree[son[a]], tree[b])); 99 return ans;100 }101 void work()102 {103 init();104 dfs1(1); dfs2(1, 1); build(1, n-1, 1);105 char s[20];106 while(scanf("%s", s) && s[0] != ‘D‘) {107 int a, b; scanf("%d%d", &a, &b);108 if(s[0] == ‘C‘) {109 change(1, n-1, 1, tree[pre[a]], b);110 }111 else {112 printf("%d\n", answer(a, b));113 }114 }115 }116 int main()117 {118 int t; cin>>t;119 while(t--) work();120 return 0;121 }
View code
Spoj-qtree-tree link splitting (edge partitioning)