Advertisement
Guest User

Yandex algo, round 1, task e

a guest
Jun 10th, 2016
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.73 KB | None | 0 0
  1. // Copyright (C) 2016 Sayutin Dmitry.
  2. //
  3. // This program is free software; you can redistribute it and/or
  4. // modify it under the terms of the GNU General Public License as
  5. // published by the Free Software Foundation; version 3
  6.  
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10. // GNU General Public License for more details.
  11.  
  12. // You should have received a copy of the GNU General Public License
  13. // along with this program; If not, see <http://www.gnu.org/licenses/>.
  14.  
  15. #include <iostream>
  16. #include <vector>
  17. #include <stdint.h>
  18. #include <algorithm>
  19. #include <set>
  20. #include <map>
  21. #include <array>
  22. #include <queue>
  23. #include <stack>
  24. #include <functional>
  25. #include <utility>
  26. #include <string>
  27. #include <assert.h>
  28. #include <iterator>
  29.  
  30. using std::cin;
  31. using std::cout;
  32. using std::cerr;
  33.  
  34. using std::vector;
  35. using std::map;
  36. using std::array;
  37. using std::set;
  38. using std::string;
  39.  
  40. using std::pair;
  41. using std::make_pair;
  42.  
  43. using std::min;
  44. using std::abs;
  45. using std::max;
  46.  
  47. using std::sort;
  48. using std::generate;
  49. using std::min_element;
  50. using std::max_element;
  51.  
  52. template <typename T>
  53. T input() {
  54.     T res;
  55.     cin >> res;
  56.     return res;
  57. }
  58.  
  59. #ifdef LOCAL
  60. #define LASSERT(X) assert(X)
  61. #else
  62. #define LASSERT(X) {}
  63. #endif
  64.  
  65. struct entry {
  66.     char type; // 0 - down, 1 - up,
  67.     size_t newv;
  68. };
  69.  
  70. vector<size_t> euler;
  71. vector<pair<size_t, size_t>> times; // [).
  72. vector<vector<size_t>> seg;
  73. vector<entry> LOG;
  74.  
  75. void dfs(size_t v, const vector<vector<size_t>>& graph, vector<char>& vis) {
  76.     vis[v] = true;
  77.     times[v].first = euler.size();
  78.    
  79.     for (size_t u: graph[v])
  80.         if (not vis[u]) {
  81.             LOG.push_back(entry {0, u});
  82.             dfs(u, graph, vis);
  83.             LOG.push_back(entry {1, v});
  84.         }
  85.    
  86.     euler.push_back(v);
  87.     times[v].second = euler.size();
  88. }
  89.  
  90. void build_seg(size_t id, size_t l, size_t r) {
  91.     if (l == r - 1) {
  92.         seg.resize(max(seg.size(), id + 1));
  93.         seg[id] = {euler[l]};
  94.     } else {
  95.         size_t mid = l + (r - l) / 2;
  96.         build_seg(2 * id + 1, l, mid);
  97.         build_seg(2 * id + 2, mid, r);
  98.        
  99.         seg[id].resize(r - l);
  100.         std::merge(seg[2 * id + 1].begin(), seg[2 * id + 1].end(), seg[2 * id + 2].begin(), seg[2 * id + 2].end(), seg[id].begin());
  101.     }
  102. }
  103.  
  104. size_t count(size_t id, size_t nl, size_t nr, size_t l, size_t r, size_t a, size_t b) {
  105.     if (l <= nl and nr <= r) {
  106.         return std::upper_bound(seg[id].begin(), seg[id].end(), b) - std::lower_bound(seg[id].begin(), seg[id].end(), a);
  107.     } else if (nr <= l or r <= nl) {
  108.         return 0;
  109.     } else {
  110.         size_t mid = nl + (nr - nl) / 2;
  111.         return count(2 * id + 1, nl, mid, l, r, a, b)
  112.             + count(2 * id + 2, mid, nr, l, r, a, b);
  113.     }
  114. }
  115.  
  116. int main() {
  117.     std::iostream::sync_with_stdio(false);
  118.     cin.tie(nullptr);
  119.     cout.tie(nullptr);
  120.  
  121.     size_t n = input<size_t>();
  122.     vector<vector<size_t>> tree(n);
  123.  
  124.     vector<size_t> prio(n);
  125.     std::generate(prio.begin(), prio.end(), input<size_t>);
  126.  
  127.     for (size_t i = 1; i != n; ++i) {
  128.         size_t v, u;
  129.         cin >> v >> u;
  130.         --v, --u;
  131.         tree[v].push_back(u);
  132.         tree[u].push_back(v);
  133.     }
  134.  
  135.     vector<char> vis(n, false);
  136.     euler.reserve(n);
  137.     times.resize(n);
  138.    
  139.     dfs(0, tree, vis);
  140.     for (auto& v: euler)
  141.         v = prio[v];
  142.  
  143.     build_seg(0, 0, n);
  144.    
  145.     pair<size_t, size_t> ans = {0, 0}; // inv, root.
  146.     size_t invroot = 0;
  147.     for (size_t v = 0; v != n; ++v) {
  148.         invroot += count(0, 0, n, times[v].first, times[v].second, prio[v] + 1, SIZE_MAX);
  149.     }
  150.  
  151. //    cout << invroot << "\n";
  152.     ans = {invroot, 0};
  153.     size_t curroot = 0;
  154.     for (size_t i = 0; i != LOG.size(); ++i) {
  155.         size_t upper;
  156.         size_t lower;
  157.         size_t newroot = LOG[i].newv;
  158.        
  159.         if (LOG[i].type == 0)
  160.             upper = curroot, lower = newroot;
  161.         else
  162.             upper = newroot, lower = curroot;
  163.  
  164.         size_t up_effect = count(0, 0, n, times[lower].first, times[lower].second, prio[upper] + 1, SIZE_MAX);
  165.         size_t lo_effect = count(0, 0, n, 0, n, prio[lower] + 1, SIZE_MAX)
  166.             - count(0, 0, n, times[lower].first, times[lower].second, prio[lower] + 1, SIZE_MAX);
  167.  
  168.         if (LOG[i].type == 1) {
  169.             invroot += up_effect;
  170.             invroot -= lo_effect;
  171.         } else {
  172.             invroot += lo_effect;
  173.             invroot -= up_effect;
  174.         }
  175.        
  176.         curroot = newroot;
  177.         ans = min(ans, {invroot, curroot});
  178.     }
  179.  
  180.     cout << ans.second + 1 << " " << ans.first << "\n";
  181.    
  182.     return 0;
  183. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement