Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define inf -123456789
- static const int MAXN = 1e5 + 5;
- static const int LOGN = 18;
- int chainNo, // number of chain
- chainHead[MAXN], // starting node of the chain
- chainInd[MAXN], // chain no of a node
- chainPos[MAXN], // position in the chain in the chain
- chainSize[MAXN], // total no of node in the chain
- baseArray[MAXN], // create an array using all chain
- posBase[MAXN], // position of a node in baseArray
- ptr, // pointer of baseArray
- depth[MAXN], // depth of a node in dfs tree
- father[MAXN][LOGN], // sparse table
- subTreeSize[MAXN], // subtree size of a node
- startNode[MAXN], // start node of an edge in dfs tree
- endNode[MAXN], // end node of an edge in dfs tree
- S, // starting index of baseArray in Segment tree
- E, // last index of baseArray
- edgeCost[MAXN]; // cost of an edge store in a node wrt to dfs tree
- struct node
- {
- int v, e, w; // v: child node, e: edge number, w: edge cost
- node(int vv = 0, int ee = 0, int ww = 0) : v(vv), e(ee), w(ww) {}
- };
- vector <node> G[MAXN];
- void DFS(int u = 1, int p = -1)
- {
- for (int i = 1; i < LOGN; i++)
- father[u][i] = father[father[u][i-1]][i-1];
- subTreeSize[u] = 1;
- for (auto &it : G[u])
- {
- int v = it.v;
- int e = it.e;
- int w = it.w;
- if (v == p)
- continue;
- depth[v] = depth[v] + 1;
- father[v][0] = u;
- startNode[e] = u;
- endNode[e] = v; // use it to update an edge
- edgeCost[v] = w;
- DFS(v, u);
- subTreeSize[u] += subTreeSize[v];
- }
- }
- int LCA(int u, int v)
- {
- if (depth[u] < depth[v])
- swap(u, v);
- for (int i = LOGN-1; i >= 0; i--)
- {
- if (depth[father[u][i]] >= depth[v])
- {
- u = father[u][i];
- }
- }
- if (u == v)
- return u;
- for (int i = LOGN-1; i >= 0; i--)
- {
- if (father[u][i] != father[v][i])
- {
- u = father[u][i];
- v = father[v][i];
- }
- }
- return father[u][0];
- }
- void HLD(int u = 1, int p = -1) // nodes are numbered from 1,2,3,………… ,n
- {
- if (chainHead[chainNo] == -1)
- chainHead[chainNo] = u;
- chainInd[u] = chainNo;
- ptr++;
- baseArray[ptr] = edgeCost[u];
- posBase[u] = ptr;
- int specialChild = -1;
- int maxSize = -1;
- for (auto &it : G[u])
- {
- int v = it.v;
- if (v == p)
- continue;
- if (subTreeSize[v] > maxSize)
- maxSize = subTreeSize[v], specialChild = v;
- }
- if (specialChild != -1)
- hld(specialChild, u);
- for (auto &it : G[u])
- {
- int v = it.v;
- if (v == p)
- continue;
- if (v != specialChild)
- {
- chainNo++;
- HLD(v, u);
- }
- }
- }
- struct SegmentTree
- {
- int maxValue;
- void assignLeaf(int val)
- {
- maxValue = val;
- }
- void Merge(SegmentTree &L, SegmentTree &R)
- {
- if (L.maxValue == inf)
- maxValue = R.maxValue;
- else if (R.maxValue == inf)
- maxValue = L.maxValue;
- else
- maxValue = max(L.maxValue, R.maxValue);
- }
- } TREE[MAXN << 2];
- void BUILD(int node, int a, int b)
- {
- if (a > b)
- return;
- if (a == b)
- {
- TREE[node].assignLeaf(baseArray[a]);
- return;
- }
- int left = node << 1;
- int right = left | 1;
- int mid = (a + b) >> 1;
- BUILD(left, a, mid);
- BUILD(right, mid+1, b);
- TREE[node].Merge(TREE[left], TREE[right]);
- }
- void UPDATE(int node, int a, int b, int pos, int value)
- {
- if (a > b || a > pos || b < pos)
- return;
- if (a >= pos && b <= pos)
- {
- TREE[node].assignLeaf(value);
- return;
- }
- int left = node << 1;
- int right = left | 1;
- int mid = (a + b) >> 1;
- UPDATE(left, a, mid, pos, value);
- UPDATE(right, mid+1, b, pos, value);
- TREE[node].Merge(TREE[left], TREE[right]);
- }
- SegmentTree QUERY(int node, int a, int b, int i, int j)
- {
- if (a > b || a > j || b < i)
- return {inf};
- if (a >= i && b <= j)
- return TREE[node];
- int left = node << 1;
- int right = left | 1;
- int mid = (a+b) >> 1;
- SegmentTree p1, p2, res;
- p1 = QUERY(left, a, mid, i, j);
- p2 = QUERY(right, mid+1, b, i, j);
- res.Merge(p1, p2);
- return res;
- }
- void CHANGE_EDGE_COST(int edgeNum, int value)
- {
- int endNodeEdge = endNode[edgeNum];
- edgeCost[endNodeEdge] = value;
- UPDATE(1, S, E, posBase[endNodeEdge], value);
- }
- int QUERY_UP(int u, int v)
- {
- // u - alwayes the lowest node, v - lca
- int uChain,
- vChain = chainInd[v],
- maxCost = inf;
- while (true)
- {
- uChain = chainInd[u];
- if (uChain == vChain)
- {
- int l = posBase[v]+1; // if node query then don’t add 1
- int r = posBase[u];
- if (l > r)
- break;
- int ans = QUERY(1, S, E, l, r).maxValue;
- maxCost = max(maxCost, ans);
- break;
- }
- int l = posBase[chainHead[uChain]];
- int r = posBase[u];
- maxCost = max(maxCost, QUERY(1, S, E, l, r).maxValue);
- u = father[chainHead[uChain]][0];
- }
- return maxCost;
- }
- int QUERY_HLD(int u, int v)
- {
- if (u == v)
- return 0;
- int lca = LCA(u, v);
- int ans = inf;
- if (u != lca)
- ans = max(ans, QUERY_UP(u, lca));
- if (v != lca)
- ans = max(ans, QUERY_UP(v, lca));
- return ans;
- }
- void INITIALIZE()
- {
- ptr = 0;
- chainNo = 0;
- for (int i = 0; i < MAXN; i++)
- {
- G[i].clear();
- subTreeSize[i] = 0;
- chainHead[i] = -1;
- chainInd[i] = 0;
- depth[i] = 0;
- baseArray[i] = 0;
- posBase[i] = 0;
- for (int j = 0; j < LOGN; j++)
- father[i][j] = 0;
- }
- }
- int main()
- {
- int tc;
- scanf("%d", &tc);
- while (tc--)
- {
- INITIALIZE();
- int tNode;
- scanf("%d", &tNode);
- for (int e = 1; e < tNode; e++)
- {
- int u, v, w;
- scanf("%d %d %d", &u, &v, &w);
- G[u].push_back({v, e, w});
- G[v].push_back({u, e, w});
- }
- int root = 1;
- edgeCost[1] = inf;
- depth[root] = 1;
- DFS();
- HLD();
- S = 1;
- E = ptr;
- BUILD(1, S, E);
- char t[7];
- while (true)
- {
- scanf("%s", t);
- if (t[0] == 'D')
- break;
- if (t[0] == 'C')
- {
- int edgeNum, value;
- scanf("%d %d", &edgeNum, &value);
- CHANGE_EDGE_COST(edgeNum, value);
- }
- else
- {
- int a, b;
- scanf("%d %d", &a, &b);
- int ans = QUERY_HLD(a, b);
- printf("%d\n", ans);
- }
- }
- }
- }
- Sample Input:
- 1
- 3
- 1 2 1
- 2 3 2
- QUERY 1 2
- CHANGE 1 3
- QUERY 1 2
- DONE
- Sample Output:
- 1
- 3
- #define inf -123456789
- static const int MAXN = 1e5 + 5;
- static const int LOGN = 18;
- int chainNo, // number of chain
- chainHead[MAXN], // starting node of the chain
- chainInd[MAXN], // chain no of a node
- chainPos[MAXN], // position in the chain in the chain
- chainSize[MAXN], // total no of node in the chain
- baseArray[MAXN], // create an array using all chain
- posBase[MAXN], // position of a node in baseArray
- ptr, // pointer of baseArray
- depth[MAXN], // depth of a node in dfs tree
- father[MAXN][LOGN], // sparse table
- subTreeSize[MAXN], // subtree size of a node
- startNode[MAXN], // start node of an edge in dfs tree
- endNode[MAXN], // end node of an edge in dfs tree
- S, // starting index of baseArray in Segment tree
- E, // last index of baseArray
- edgeCost[MAXN]; // cost of an edge store in a node wrt to dfs tree
- struct node
- {
- int v, e, w; // v: child node, e: edge number, w: edge cost
- node(int vv = 0, int ee = 0, int ww = 0) : v(vv), e(ee), w(ww) {}
- };
- vector <node> G[MAXN];
- void DFS(int u = 1, int p = -1)
- {
- for (int i = 1; i < LOGN; i++)
- father[u][i] = father[father[u][i-1]][i-1];
- subTreeSize[u] = 1;
- for (auto &it : G[u])
- {
- int v = it.v;
- int e = it.e;
- int w = it.w;
- if (v == p)
- continue;
- depth[v] = depth[v] + 1;
- father[v][0] = u;
- startNode[e] = u;
- endNode[e] = v; // use it to update an edge
- edgeCost[v] = w;
- DFS(v, u);
- subTreeSize[u] += subTreeSize[v];
- }
- }
- int LCA(int u, int v)
- {
- if (depth[u] < depth[v])
- swap(u, v);
- for (int i = LOGN-1; i >= 0; i--)
- {
- if (depth[father[u][i]] >= depth[v])
- {
- u = father[u][i];
- }
- }
- if (u == v)
- return u;
- for (int i = LOGN-1; i >= 0; i--)
- {
- if (father[u][i] != father[v][i])
- {
- u = father[u][i];
- v = father[v][i];
- }
- }
- return father[u][0];
- }
- void HLD(int u = 1, int p = -1) // nodes are numbered from 1,2,3,………… ,n
- {
- if (chainHead[chainNo] == -1)
- chainHead[chainNo] = u;
- chainInd[u] = chainNo;
- ptr++;
- baseArray[ptr] = edgeCost[u];
- posBase[u] = ptr;
- int specialChild = -1;
- int maxSize = -1;
- for (auto &it : G[u])
- {
- int v = it.v;
- if (v == p)
- continue;
- if (subTreeSize[v] > maxSize)
- maxSize = subTreeSize[v], specialChild = v;
- }
- if (specialChild != -1)
- hld(specialChild, u);
- for (auto &it : G[u])
- {
- int v = it.v;
- if (v == p)
- continue;
- if (v != specialChild)
- {
- chainNo++;
- HLD(v, u);
- }
- }
- }
- struct SegmentTree
- {
- int maxValue;
- void assignLeaf(int val)
- {
- maxValue = val;
- }
- void Merge(SegmentTree &L, SegmentTree &R)
- {
- if (L.maxValue == inf)
- maxValue = R.maxValue;
- else if (R.maxValue == inf)
- maxValue = L.maxValue;
- else
- maxValue = max(L.maxValue, R.maxValue);
- }
- } TREE[MAXN << 2];
- void BUILD(int node, int a, int b)
- {
- if (a > b)
- return;
- if (a == b)
- {
- TREE[node].assignLeaf(baseArray[a]);
- return;
- }
- int left = node << 1;
- int right = left | 1;
- int mid = (a + b) >> 1;
- BUILD(left, a, mid);
- BUILD(right, mid+1, b);
- TREE[node].Merge(TREE[left], TREE[right]);
- }
- void UPDATE(int node, int a, int b, int pos, int value)
- {
- if (a > b || a > pos || b < pos)
- return;
- if (a >= pos && b <= pos)
- {
- TREE[node].assignLeaf(value);
- return;
- }
- int left = node << 1;
- int right = left | 1;
- int mid = (a + b) >> 1;
- UPDATE(left, a, mid, pos, value);
- UPDATE(right, mid+1, b, pos, value);
- TREE[node].Merge(TREE[left], TREE[right]);
- }
- SegmentTree QUERY(int node, int a, int b, int i, int j)
- {
- if (a > b || a > j || b < i)
- return {inf};
- if (a >= i && b <= j)
- return TREE[node];
- int left = node << 1;
- int right = left | 1;
- int mid = (a+b) >> 1;
- SegmentTree p1, p2, res;
- p1 = QUERY(left, a, mid, i, j);
- p2 = QUERY(right, mid+1, b, i, j);
- res.Merge(p1, p2);
- return res;
- }
- void CHANGE_EDGE_COST(int edgeNum, int value)
- {
- int endNodeEdge = endNode[edgeNum];
- edgeCost[endNodeEdge] = value;
- UPDATE(1, S, E, posBase[endNodeEdge], value);
- }
- int QUERY_UP(int u, int v)
- {
- // u - alwayes the lowest node, v - lca
- int uChain,
- vChain = chainInd[v],
- maxCost = inf;
- while (true)
- {
- uChain = chainInd[u];
- if (uChain == vChain)
- {
- int l = posBase[v]+1; // if node query then don’t add 1
- int r = posBase[u];
- if (l > r)
- break;
- int ans = QUERY(1, S, E, l, r).maxValue;
- maxCost = max(maxCost, ans);
- break;
- }
- int l = posBase[chainHead[uChain]];
- int r = posBase[u];
- maxCost = max(maxCost, QUERY(1, S, E, l, r).maxValue);
- u = father[chainHead[uChain]][0];
- }
- return maxCost;
- }
- int QUERY_HLD(int u, int v)
- {
- if (u == v)
- return 0;
- int lca = LCA(u, v);
- int ans = inf;
- if (u != lca)
- ans = max(ans, QUERY_UP(u, lca));
- if (v != lca)
- ans = max(ans, QUERY_UP(v, lca));
- return ans;
- }
- void INITIALIZE()
- {
- ptr = 0;
- chainNo = 0;
- for (int i = 0; i < MAXN; i++)
- {
- G[i].clear();
- subTreeSize[i] = 0;
- chainHead[i] = -1;
- chainInd[i] = 0;
- depth[i] = 0;
- baseArray[i] = 0;
- posBase[i] = 0;
- for (int j = 0; j < LOGN; j++)
- father[i][j] = 0;
- }
- }
- int main()
- {
- int tc;
- scanf("%d", &tc);
- while (tc--)
- {
- INITIALIZE();
- int tNode;
- scanf("%d", &tNode);
- for (int e = 1; e < tNode; e++)
- {
- int u, v, w;
- scanf("%d %d %d", &u, &v, &w);
- G[u].push_back({v, e, w});
- G[v].push_back({u, e, w});
- }
- int root = 1;
- edgeCost[1] = inf;
- depth[root] = 1;
- DFS();
- HLD();
- S = 1;
- E = ptr;
- BUILD(1, S, E);
- char t[7];
- while (true)
- {
- scanf("%s", t);
- if (t[0] == 'D')
- break;
- if (t[0] == 'C')
- {
- int edgeNum, value;
- scanf("%d %d", &edgeNum, &value);
- CHANGE_EDGE_COST(edgeNum, value);
- }
- else
- {
- int a, b;
- scanf("%d %d", &a, &b);
- int ans = QUERY_HLD(a, b);
- printf("%d\n", ans);
- }
- }
- }
- }
- Sample Input:
- 1
- 3
- 1 2 1
- 2 3 2
- QUERY 1 2
- CHANGE 1 3
- QUERY 1 2
- DONE
- Sample Output:
- 1
- 3
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement