Advertisement
tien_noob

Manhattan MST - (Sol LMH)

Nov 11th, 2022
757
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.23 KB | None | 0 0
  1. #define taskname "DESERT"
  2. #include <iostream>
  3. #include <cstdio>
  4. #include <algorithm>
  5. #include <cstdlib>
  6. #include <vector>
  7. #include <queue>
  8. using namespace std;
  9. const int maxN = 1e5;
  10. using lli = long long;
  11. const lli infty = 4e9 + 1;
  12.  
  13. struct TPoint
  14. {
  15.     int x, y;
  16.     inline int SumXY() const
  17.     {
  18.         return x + y;
  19.     }
  20. };
  21. using PPoint = TPoint*;
  22.  
  23. int n, m;
  24. TPoint p[maxN];
  25. PPoint pp[maxN];
  26. int xarr[maxN];
  27. PPoint tree[maxN + 1];
  28. lli d[maxN];
  29. int trace[maxN];
  30. bool OutTree[maxN];
  31.  
  32. struct TPQNode
  33. {
  34.     int u;
  35.     lli dlab;
  36.     inline bool Valid() const
  37.     {
  38.         return dlab == d[u];
  39.     }
  40.     inline bool operator < (const TPQNode& other) const
  41.     {
  42.         return dlab > other.dlab;
  43.     }
  44. };
  45.  
  46. struct TEdge
  47. {
  48.     int u, v;
  49.     inline lli Weight() const
  50.     {
  51.         return lli(abs(p[u].x - p[v].x)) + abs(p[u].y - p[v].y);
  52.     }
  53. };
  54. using PEdge = TEdge*;
  55. TEdge e[8 * maxN];
  56. vector<PEdge> adj[maxN];
  57.  
  58. inline bool Minimize(lli& Target, lli Value)
  59. {
  60.     if (Value < Target)
  61.     {
  62.         Target = Value;
  63.         return true;
  64.     }
  65.     return false;
  66. }
  67.  
  68. void ReadInput()
  69. {
  70.     cin >> n;
  71.     for (int i = 0; i < n; ++i)
  72.     {
  73.         cin >> p[i].x >> p[i].y;
  74.         pp[i] = &p[i];
  75.     }
  76.     m = 0;
  77. }
  78.  
  79. inline int XIdx(int x)
  80. {
  81.     return upper_bound(xarr, xarr + n, x) - xarr;
  82. }
  83.  
  84. inline void Update(int pos, PPoint p)
  85. {
  86.     for (; pos <= n; pos += pos & -pos)
  87.         if (tree[pos] == nullptr || tree[pos]->SumXY() < p->SumXY())
  88.             tree[pos] = p;
  89.         else
  90.             break;
  91. }
  92.  
  93. inline PPoint Query(int pos)
  94. {
  95.     PPoint res = nullptr;
  96.     for (; pos > 0; pos &= pos - 1)
  97.     {
  98.         if (tree[pos] == nullptr) continue;
  99.         if (res == nullptr || res->SumXY() < tree[pos]->SumXY())
  100.             res = tree[pos];
  101.     }
  102.     return res;
  103. }
  104.  
  105. void Sweepline()
  106. {
  107.     for (int i = 0; i < n; ++i)
  108.         xarr[i] = p[i].x;
  109.     sort(xarr, xarr + n);
  110.     sort(pp, pp + n, [](PPoint p, PPoint q)
  111.     {
  112.         if (p->x - p->y != q->x - q->y)
  113.             return p->x - p->y > q->x - q->y;
  114.         else
  115.             return p->x < q->x;
  116.     });
  117.     fill(tree + 1, tree + n + 1, nullptr);
  118.     for (int i = 0; i < n; ++i)
  119.     {
  120.         int u = pp[i] - p;
  121.         int pos = XIdx(pp[i]->x);
  122.         PPoint q = Query(pos);
  123.         if (q != nullptr)
  124.         {
  125.             int v = q - p;
  126.             e[m++] = {u, v};
  127.         }
  128.         Update(pos, pp[i]);
  129.     }
  130. }
  131.  
  132. void Rot90()
  133. {
  134.     for (int i = 0; i < n; ++i)
  135.     {
  136.         int temp = p[i].x;
  137.         p[i].x = -p[i].y;
  138.         p[i].y = temp;
  139.     }
  140. }
  141.  
  142. void Mirror()
  143. {
  144.     for (int i = 0; i < n; ++i)
  145.         p[i].x = -p[i].x;
  146. }
  147.  
  148. void GetEdges()
  149. {
  150.     m = 0;
  151.     for (int rot = 0; rot < 4; ++rot)
  152.     {
  153.         Sweepline();
  154.         Rot90();
  155.     }
  156.     Mirror();
  157.     for (int rot = 0; rot < 4; ++rot)
  158.     {
  159.         Sweepline();
  160.         Rot90();
  161.     }
  162. }
  163.  
  164. void BuildAdjs()
  165. {
  166.     for (int i = 0; i < m; ++i)
  167.     {
  168.         adj[e[i].u].push_back(&e[i]);
  169.         adj[e[i].v].push_back(&e[i]);
  170.     }
  171. }
  172.  
  173. void Prim()
  174. {
  175.     fill(trace, trace + n, -1);
  176.     fill(OutTree, OutTree + n, true);
  177.     fill(d, d + n, infty);
  178.     d[n - 1] = 0;
  179.     OutTree[n - 1] = false;
  180.     priority_queue<TPQNode> PQ;
  181.     PQ.push({n - 1, 0});
  182.     while (true)
  183.     {
  184.         TPQNode Node = PQ.top();
  185.         PQ.pop();
  186.         if (!Node.Valid()) continue;
  187.         int u = Node.u;
  188.         if (u == 0) break;
  189.         OutTree[u] = false;
  190.         for (PEdge e: adj[u])
  191.         {
  192.             int v = e->u ^ e->v ^ u;
  193.             if (!OutTree[v]) continue;
  194.             if (Minimize(d[v], e->Weight()))
  195.             {
  196.                 PQ.push({v, d[v]});
  197.                 trace[v] = u;
  198.             }
  199.         }
  200.     }
  201. }
  202.  
  203. void PrintResult()
  204. {
  205.     lli Volume = 0;
  206.     for (int s = 0; s != n - 1; s = trace[s])
  207.         if (d[s] > Volume) Volume = d[s];
  208.     cout << Volume << '\n';
  209.     for (int s = 0; s != n - 1; s = trace[s])
  210.         cout << s + 1 << ' ';
  211.     cout << n;
  212. }
  213.  
  214. int main()
  215. {
  216.     ios_base::sync_with_stdio(false);
  217.     cin.tie(nullptr);
  218.     freopen(taskname".INP", "r", stdin);
  219.     freopen(taskname".OUT", "w", stdout);
  220.     ReadInput();
  221.     GetEdges();
  222.     BuildAdjs();
  223.     Prim();
  224.     PrintResult();
  225. }
  226.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement