mr_dot_convict

12533-UVa-Joining_Couples-mr.convict

Oct 19th, 2019
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.40 KB | None | 0 0
  1. // Hack it and have it ;) //
  2. /*author* Priyanshu Shrivastav (from IIT Palakkad) *
  3.  * *_ __ ___  _ ______ ___  _ ____   ___  ___| |_  *
  4.  * | '_ ` _ \| '__/ __/ _ \| '_ \ \ / / |/ __| __| *
  5.  * | | | | | | | | (_| (_) | | | \ V /| | (__| |_  *
  6.  * |_| |_| |_|_|(_)___\___/|_| |_|\_/ |_|\___|\__| *
  7. When I wrote this, only God and I understood what I was doing
  8.  ** * * * * * * * Now, only God knows!* * * * * * */
  9. #include      <bits/stdc++.h> /*{{{*/
  10. #include      <ext/pb_ds/assoc_container.hpp>
  11. #include      <ext/pb_ds/tree_policy.hpp>
  12. using namespace std;
  13. using namespace __gnu_pbds;
  14.  
  15. #ifndef CONVICTION
  16. #pragma GCC       optimize ("Ofast")
  17. #pragma GCC       optimize ("unroll-loops")
  18. #pragma GCC       target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
  19. #endif
  20.  
  21. #define IOS       ios_base::sync_with_stdio(false); cin.tie (nullptr)
  22. #define PREC      cout.precision (10); cout << fixed
  23. #define x         first
  24. #define y         second
  25. #define fr(i,x,y) for (int i = x; i <= y; ++i)
  26. #define fR(i,x,y) for (int i = x; i >= y; --i)
  27. #define cnt(x)    __buildin_popcount(x)
  28. #define cntll(x)  __buildin_popcountll(x)
  29. #define bg(x)     " [ " << #x << " : " << (x) << " ] "
  30. #define un(x)     sort(x.begin(), x.end()), \
  31.    x.erase(unique(x.begin(), x.end()), x.end())
  32. using   ll  =     long long;
  33. using   ull =     unsigned long long;
  34. using   ff  =     long double;
  35. using   pii =     pair<int,int>;
  36. using   pil =     pair<int,ll>;
  37. typedef tree
  38. < int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>
  39. ordered_set;
  40.  
  41. struct chash {
  42.    int operator () (pii x) const { return x.x*31 + x.y; }
  43. };
  44. gp_hash_table <pii, int, chash> mp;
  45.  
  46. #if __cplusplus > 201103L
  47. seed_seq seq{
  48.    (uint64_t) chrono::duration_cast<chrono::nanoseconds>
  49.       (chrono::high_resolution_clock::now().time_since_epoch()).count(),
  50.       (uint64_t) __builtin_ia32_rdtsc(),
  51.       (uint64_t) (uintptr_t) make_unique<char>().get()
  52. };
  53. mt19937 rng(seq); //uniform_int_distribution<int> (l, h)(rng); //[low, high]
  54. #else
  55. auto seed = chrono::high_resolution_clock::now().time_since_epoch().count();
  56. mt19937 rng(seed);
  57. #endif
  58.  
  59. #define debug(args...) { \
  60.    /* WARNING : do NOT compile this debug func calls with following flags: // \
  61.     * // -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -D_FORTIFY_SOURCE=2*/ \
  62.    string _s = #args; replace(_s.begin(), _s.end(), ',', ' ');\
  63.    stringstream _ss(_s); \
  64.    istream_iterator<string> _it(_ss); err(_it, args); \
  65. }
  66. void err(istream_iterator<string> it) {
  67.    it->empty(); cerr << " (Line : " << __LINE__ << ")" << '\n';
  68. }
  69. template<typename T, typename... Args>
  70. void err(istream_iterator<string> it, T a, Args... args) {
  71.    cerr << fixed << setprecision(15)
  72.       << " [ " <<  *it << " : " << a  << " ] "<< ' ';
  73.    err(++it, args...);
  74. }
  75. /*}}}*/
  76. /*****************************************************************************/
  77. //Don’t practice until you get it right. Practice until you can’t get it wrong
  78.  
  79. signed main() {
  80.    IOS; PREC;
  81.    int n;
  82.    while (cin >> n) {
  83.       vector <vector <int>> uT(n, vector <int>());
  84.       vector <int> pi(n, -1);
  85.       for (int i = 0; i < n; ++i) {
  86.          cin >> pi[i];
  87.          --pi[i];
  88.          uT[i].push_back(pi[i]);
  89.          uT[pi[i]].push_back(i);
  90.       }
  91.  
  92.       vector <bool> vis(n, false);
  93.       vector <int> cc(n, -1);
  94.  
  95.       function <void(int, int)> dfs = [&] (int u, int cc_idx) -> void {
  96.          vis[u] = true;
  97.          cc[u] = cc_idx;
  98.          for (int v : uT[u]) if (!vis[v]) dfs(v, cc_idx);
  99.       };
  100.  
  101.  
  102.       int cc_idx = 0;
  103.       for (int u = 0; u < n; ++u)
  104.          if (!vis[u]) dfs(u, cc_idx++);
  105.  
  106.       /////////////////////////////////////////////////////
  107.       vector <int> root(cc_idx, -1);
  108.  
  109.       vis.assign(n, false);
  110.       function <void(int, int)> dfs2 =
  111.          [&] (int u, int pr) -> void{
  112.             vis[u] = true;
  113.  
  114.             for (int v : uT[u]) if (v != pr) {
  115.                if (vis[v]) root[cc[v]] = v;
  116.                else dfs2 (v, u);
  117.             }
  118.          };
  119.  
  120.       for (int i = 0; i < n; ++i) {
  121.          if (!vis[i]) dfs2(i, -1);
  122.          if (pi[pi[i]] == i) root[cc[i]] = i;
  123.       }
  124.  
  125.       vector <bool> take(n, false);
  126.       for (int i = 0; i < cc_idx; ++i)
  127.          if (root[i] != -1) take[root[i]] = true;
  128.  
  129.       vector <vector <int>> T(n + n, vector <int>());
  130.       for (int i = 0; i < n; ++i) {
  131.          if (!take[i]) {
  132.             T[pi[i]].push_back(i);
  133.             T[pi[i] + n].push_back(i + n);
  134.          }
  135.          else {
  136.             T[pi[i]].push_back(i + n);
  137.          }
  138.       }
  139.       /////////////////////////////////////////////////////
  140.  
  141.       const int D = 21;
  142.       vector <vector <int>> table(n+n, vector <int>(D + 1, -1));
  143.       vector <int> depth(n+n, 0);
  144.  
  145.       function <void(int, int)> dfs3 = [&] (int u, int d) -> void {
  146.          depth[u] = d;
  147.          for (int k = 1; k <= D; ++k) if (table[u][k-1] != -1) {
  148.             table[u][k] = table[table[u][k-1]][k-1];
  149.          }
  150.          for (int v : T[u]) {
  151.             table[v][0] = u;
  152.             dfs3(v, d+1);
  153.          }
  154.       };
  155.  
  156.       for (int i = 0; i < cc_idx; ++i) {
  157.          dfs3(root[i], 0);
  158.       }
  159.  
  160.       auto walk = [&] (int u, int l) -> int {
  161.          for (int d = 0; d <= D && u >= 0; ++d)
  162.             if ((1 << d) & l)
  163.                u = table[u][d];
  164.          return u;
  165.       };
  166.  
  167.       auto lca = [&] (int u, int v) -> int {
  168.          if (depth[v] > depth[u]) v = walk(v, depth[v] - depth[u]);
  169.          if (depth[u] > depth[v]) u = walk(u, depth[u] - depth[v]);
  170.          if (u == v) return u;
  171.  
  172.          for (int d = D; d >= 0; --d) {
  173.             if (table[u][d] == table[v][d]) continue;
  174.             u = table[u][d], v = table[v][d];
  175.          }
  176.          assert(table[u][0] == table[v][0]);
  177.          return table[u][0];
  178.       };
  179.  
  180.       /////////////////////////////////////////////////////
  181.       int q; cin >> q;
  182.       while (q--) {
  183.          int u, v;
  184.          cin >> u >> v; --u, --v;
  185.          if (cc[u] != cc[v]) cout << -1 << '\n';
  186.          else {
  187.             int mn = INT_MAX;
  188.             int U[] = {u, u + n};
  189.             int V[] = {v, v + n};
  190.             for (int i = 0; i < 2; ++i) for (int j = 0; j < 2; ++j) {
  191.                int u_ = U[i], v_ = V[j];
  192.                int z = lca(u_, v_);
  193.                mn = min(mn, depth[u_] - depth[z] + depth[v_] - depth[z]);
  194.             }
  195.             cout << mn << '\n';
  196.          }
  197.       }
  198.    }
  199.  
  200.    return EXIT_SUCCESS;
  201. }
Add Comment
Please, Sign In to add comment