PaulGraphov

Untitled

Apr 28th, 2018
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.86 KB | None | 0 0
  1. #include <iostream>
  2. #include <utility>
  3. #include <vector>
  4. #include <stack>
  5. #include <unordered_set>
  6. #include <cmath>
  7. #include <tuple>
  8. #include <cassert>
  9. #include <algorithm>
  10.  
  11. using namespace std;
  12.  
  13. using Graph = vector<vector<int>>;
  14.  
  15. struct MaxTree {
  16.     // cluster's parent cluster
  17.     vector<int> clusterParents;
  18.     // portal node in parent cluster
  19.     vector<int> clusterPortals;
  20.    
  21.     // inner cluster trees
  22.     vector<Graph> clusters;
  23.     // links to parent nodes inside clusters
  24.     vector<vector<int>> reverseClusters;
  25.    
  26.     // maps initial tree nodes to cluster and node inside the cluster
  27.     vector<pair<int, int>> clusterMap;
  28.    
  29.     // radioactivity of every node of every cluster
  30.     vector<vector<int>> levels;
  31.     // maximum radioactivity on from cluster root to each node in the cluster.
  32.     vector<vector<int>> maxLevels;
  33.    
  34.     MaxTree(const Graph& tree) : clusterMap(tree.size()), clusterParents(1), clusterPortals(1) {
  35.         int n = tree.size();
  36.         int maxClusterSize = int(round(sqrt(n)));
  37.         int clusterNo = 0;
  38.        
  39.         // parent of each node in the original tree
  40.         vector<int> parents(n);
  41.        
  42.         stack<int> queue;
  43.         queue.push(0);
  44.        
  45.         Graph cluster;
  46.         vector<int> reverseCluster;
  47.         while(!queue.empty()) {
  48.             // get next node
  49.             int node = queue.top();
  50.             queue.pop();
  51.            
  52.             int parentCluster, parentClusterNode;
  53.             tie(parentCluster, parentClusterNode) = clusterMap[parents[node]];
  54.            
  55.             // current node is going to be cluster root
  56.             if (node != 0 && (parentCluster != clusterNo || cluster.size() >= maxClusterSize)) {
  57.                 clusterNo++;
  58.                 // save cluster and start new
  59.                 clusters.push_back(move(cluster));
  60.                 reverseClusters.push_back(move(reverseCluster));
  61.                 cluster = Graph();
  62.                 reverseCluster = vector<int>();
  63.                 // link to parent cluster
  64.                 clusterParents.push_back(parentCluster);
  65.                 clusterPortals.push_back(parentClusterNode);
  66.             }
  67.            
  68.             int clusterNode = cluster.size();
  69.             cluster.push_back(vector<int>());
  70.             if (clusterNode != 0) {
  71.                 cluster[parentClusterNode].push_back(clusterNode);
  72.                 reverseCluster.push_back(parentClusterNode);
  73.             } else {
  74.                 reverseCluster.push_back(0);
  75.             }
  76.            
  77.             clusterMap[node] = {clusterNo, clusterNode};
  78.            
  79.             for (int child: tree[node]) {
  80.                 if (child == parents[node]) continue;
  81.                 parents[child] = node;
  82.                 queue.push(child);
  83.             }
  84.         }
  85.        
  86.         if (cluster.size() > 0) {
  87.             clusters.push_back(move(cluster));
  88.             reverseClusters.push_back(move(reverseCluster));
  89.         }
  90.        
  91.         for (int i = 0; i < clusters.size(); i++) {
  92.             int clusterSize = clusters[i].size();
  93.             levels.push_back(vector<int>(clusterSize));
  94.             maxLevels.push_back(vector<int>(clusterSize));
  95.         }
  96.     }
  97.    
  98.     void increase(int c, int v) {
  99.         int cluster, node;
  100.         tie(cluster, node) = clusterMap[c];
  101.         int level = (levels[cluster][node] += v);
  102.         propagateMax(cluster, node, level);
  103.     }
  104.    
  105.     void propagateMax(int cluster, int start, int level) {
  106.         stack<int> queue;
  107.         queue.push(start);
  108.        
  109.         while (!queue.empty()) {
  110.             int node = queue.top();
  111.             queue.pop();
  112.             if (maxLevels[cluster][node] >= level) continue;
  113.             maxLevels[cluster][node] = level;
  114.             for (int child : clusters[cluster][node]) {
  115.                 queue.push(child);
  116.             }
  117.         }
  118.     }
  119.    
  120.     int query(int f, int t) {
  121.         int fromCluster, fromNode, toCluster, toNode;
  122.         tie(fromCluster, fromNode) = clusterMap[f];
  123.         tie(toCluster, toNode) = clusterMap[t];
  124.        
  125.         int topCluster = getTop(clusterParents, fromCluster, toCluster);
  126.        
  127.         int fromTopNode, toTopNode, fromMaxBottom, toMaxBottom;
  128.         tie(fromTopNode, fromMaxBottom) = walkLeg(fromNode, fromCluster, topCluster);
  129.         tie(toTopNode, toMaxBottom) = walkLeg(toNode, toCluster, topCluster);
  130.         int maxTop = walkElbow(topCluster, fromTopNode, toTopNode);
  131.        
  132.         return max({fromMaxBottom, toMaxBottom, maxTop});
  133.     }
  134.    
  135.     vector<int> pathToRoot(const vector<int> &parents, int node) {
  136.         vector<int> result;
  137.         result.push_back(node);
  138.         while (node != 0) {
  139.             node = parents[node];
  140.             result.push_back(node);
  141.         }
  142.         return result;
  143.     }
  144.    
  145.     int getTop(const vector<int> &parents, int from, int to) {
  146.         vector<int> fromPath, toPath;
  147.         fromPath = pathToRoot(parents, from);
  148.         toPath = pathToRoot(parents, to);
  149.        
  150.         int result;
  151.        
  152.         while (!fromPath.empty() && !toPath.empty() && fromPath.back() == toPath.back()) {
  153.             result = fromPath.back();
  154.             fromPath.pop_back();
  155.             toPath.pop_back();
  156.         }
  157.         return result;
  158.     }
  159.  
  160.     pair<int, int> walkLeg(int node, int cluster, int top) {
  161.         int maxLevel = 0;
  162.         while (cluster != top) {
  163.             maxLevel = max(maxLevel, maxLevels[cluster][node]);
  164.             node = clusterPortals[cluster];
  165.             cluster = clusterParents[cluster];
  166.         }
  167.         return {node, maxLevel};
  168.     }
  169.    
  170.     int walkElbow(int cluster, int from, int to) {
  171.         const auto &parents = reverseClusters[cluster];
  172.         int topNode = getTop(reverseClusters[cluster], from, to);
  173.         vector<int> fromPath, toPath;
  174.         int fromMax = walkHand(cluster, from, topNode);
  175.         int toMax = walkHand(cluster, to, topNode);
  176.         return max(fromMax, toMax);
  177.     }
  178.    
  179.     int walkHand(int cluster, int from, int top) {
  180.         int maxLevel = levels[cluster][from];
  181.         while (from != top) {
  182.             assert(from != 0);
  183.             from = reverseClusters[cluster][from];
  184.             maxLevel = max(maxLevel, levels[cluster][from]);
  185.         }
  186.         return maxLevel;
  187.     }
  188. };
  189.  
  190. int main(int argc, char **argv) {
  191.     ios_base::sync_with_stdio(false);
  192.     int n;
  193.     cin >> n;
  194.     Graph mainTree(n);
  195.     for (int i = 0; i < n-1; i++) {
  196.         int f, t;
  197.         cin >> f >> t;
  198.         mainTree[f-1].push_back(t-1);
  199.         mainTree[t-1].push_back(f-1);
  200.     }
  201.    
  202.     int q;
  203.     cin >> q;
  204.     MaxTree ct(mainTree);
  205.     for (int i = 0; i < q; i++) {
  206.         char c;
  207.         int u,v;
  208.         cin >> c >> u >> v;
  209.         if (c == 'I') {
  210.             ct.increase(u-1, v);
  211.         } else if (c == 'G') {
  212.             cout << ct.query(u-1, v-1) << '\n';
  213.         }
  214.     }
  215. }
Advertisement
Add Comment
Please, Sign In to add comment