Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cstdio>
- #include <queue>
- #include <vector>
- using namespace std;
- struct Edge;
- struct Node {
- Edge *parentedge = NULL;
- int layer;
- int size;
- int chainid;
- vector<Edge *> edges;
- Node() {
- layer = -1;
- size = -1;
- chainid = -1;
- }
- };
- struct Edge {
- pair<Node *, Node *> nodes;
- int cost;
- int chainid;
- Edge() {
- cost = -1;
- chainid = -1;
- }
- Node *getother(Node *currnode) {
- if (currnode == nodes.first) {
- return nodes.second;
- } else {
- return nodes.first;
- }
- }
- };
- int log2(int n) {
- int result = -1;
- while (n) {
- result++;
- n >>= 1;
- }
- return result;
- }
- int pow2(int n) {
- return 1 << n;
- }
- void hld(vector<Node> &nodes, vector<pair<Edge *, Edge*> > &chains, Node *currnode) {
- if (currnode->edges.size() == 1) {
- currnode->size = 1;
- return;
- }
- currnode->size = 1;
- for (int i = 0; i < currnode->edges.size(); i++) {
- Edge *edge = currnode->edges[i];
- Node *next = edge->getother(currnode);
- hld(nodes, chains, next);
- currnode->size += next->size;
- }
- for (int i = 0; i < currnode->edges.size(); i++) {
- Edge *edge = currnode->edges[i];
- Node *next = edge->getother(currnode);
- if (next->size * 2 > currnode->size) {
- if (edge->chainid == -1) {
- edge->chainid = next->chainid = (int) chains.size();
- chains.push_back(make_pair((Edge *) NULL, edge));
- }
- edge->chainid = currnode->chainid = next->chainid;
- chains[edge->chainid].first = edge;
- break;
- } else if (next->chainid != -1) {
- next->chainid = -1;
- }
- }
- }
- void buildsegtree(vector<int> &segtree, vector<int> &numbers) {
- segtree = vector<int>(pow2(log2((int) numbers.size()) + 1));
- for (int i = 0; i < numbers.size(); i++) {
- segtree[i + segtree.size()/2] = numbers[i];
- }
- for (int i = numbers.size() / 2 - 1; i; i--) {
- segtree[i] = max(segtree[i<<1], segtree[i<<1|1]);
- }
- }
- void segtreeset(vector<int> &segtree, int i, int n) {
- i += segtree.size() / 2;
- segtree[i] = n;
- i >>= 1;
- for (; i; i >>= 1) segtree[i] = max(segtree[i << 1], segtree[i<<1|1]);
- }
- int segtreemaxrange(vector<int> &segtree, int l, int r) {
- int m = 0;
- while (r > l) {
- if (l&1) {
- m = max(m, segtree[l]);
- l++;
- }
- if (~r&1) {
- m = max(m, segtree[r]);
- r--;
- }
- l >>= 1;
- r >>= 1;
- if (r == l)
- m = max(m, segtree[l]);
- }
- return m;
- }
- int main() {
- int t;
- scanf("%d", &t);
- for (int _ = 0; _ < t; _++) {
- int n;
- scanf("%d", &n);
- vector<Node> nodes(n);
- vector<Edge> edges(n - 1);
- for (int i = 0; i < n - 1; i++) {
- int a, b, c;
- scanf("%d %d %d", &a, &b, &c);
- a--;
- b--;
- edges[i].nodes = make_pair(&nodes[a], &nodes[b]);
- edges[i].cost = c;
- nodes[a].edges.push_back(&edges[i]);
- nodes[b].edges.push_back(&edges[i]);
- }
- nodes.front().layer = 0;
- queue<Node *> bfs;
- bfs.push(&nodes.front());
- while (bfs.size()) {
- Node *currnode = bfs.front();
- bfs.pop();
- for (int i = 0; i < currnode->edges.size(); i++) {
- Edge *edge = currnode->edges[i];
- Node *next = edge->getother(currnode);
- if (!next->parentedge) {
- next->parentedge = edge;
- next->layer = currnode->layer + 1;
- bfs.push(next);
- }
- }
- }
- for (int i = 0; i < n - 1; i++) {
- if (edges[i].nodes.first->layer > edges[i].nodes.second->layer) {
- swap(edges[i].nodes.first, edges[i].nodes.second);
- }
- }
- vector<pair<Edge *, Edge *> > chains;
- hld(nodes, chains, &nodes.front());
- vector<vector<int> > chainsegtrees;
- for (int i = 0; i < chains.size(); i++) {
- pair<Edge *, Edge *> chain = chains[i];
- vector<int> edgelengths(chain.second->nodes.second->layer - chain.first->nodes.second->layer);
- Node *currnode = chain.second->nodes.second;
- while (currnode != chain.first->nodes.first) {
- edgelengths[currnode->layer - chain.first->nodes.first->layer - 1] = currnode->parentedge->cost;
- currnode = currnode->parentedge->getother(currnode);
- }
- chainsegtrees.push_back(vector<int>());
- buildsegtree(chainsegtrees.back(), edgelengths);
- }
- while (true) {
- char command;
- {
- do {
- command = getchar();
- } while (command == ' ' || command == '\n');
- char tmp;
- do {
- tmp = getchar();
- } while (tmp != ' ' && tmp != '\n');
- }
- if (command == 'D') {
- break;
- } else if (command == 'C') {
- int a, c;
- scanf("%d %d", &a, &c);
- a--;
- edges[a].cost = c;
- if (edges[a].chainid != -1) {
- int segi = edges[a].nodes.first->layer - chains[edges[a].chainid].first->nodes.first->layer;
- segtreeset(chainsegtrees[nodes[a].layer], segi, c);
- }
- } else {
- int a, b;
- scanf("%d %d", &a, &b);
- a--;
- b--;
- Node *nodea = &nodes[a];
- Node *nodeb = &nodes[b];
- long long result = 0;
- while (nodea != nodeb && (nodea->chainid == -1 || nodea->chainid != nodeb->chainid)) {
- if (nodea->layer > nodeb->layer) {
- if (nodea->chainid != -1) {
- nodea = chains[nodea->chainid].first->nodes.first;
- } else {
- result = max(result, (long long) nodea->parentedge->cost);
- nodea = nodea->parentedge->getother(nodea);
- }
- } else {
- if (nodeb->chainid != -1) {
- nodeb = chains[nodeb->chainid].first->nodes.first;
- } else {
- result = max(result, (long long) nodeb->parentedge->cost);
- nodeb = nodeb->parentedge->getother(nodeb);
- }
- }
- }
- if (nodea != nodeb && nodea->chainid == nodeb->chainid) {
- result = max(result, (long long) segtreemaxrange(chainsegtrees[nodea->chainid],
- nodea->layer - chains[nodea->chainid].first->nodes.first->layer,
- nodeb->layer - chains[nodeb->chainid].first->nodes.first->layer - 1));
- }
- printf("%lld\n", result);
- }
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement