Advertisement
Bobert0032

Пособие/«Парковка»

Sep 21st, 2023 (edited)
687
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.19 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3.  
  4. using namespace std;
  5.  
  6. vector<int> par, sz; // создаём вектора par(массив ссылок), sz(массив размеров множеств)
  7. vector<int> gm; // gm[i] = j означает, что максимальный номер места в блоке, содержащем i-ое место, - это x
  8.  
  9. int get_par(int v) { // get_par(v) возвращает номер блока, к которому принадлежит v-ое место
  10.     if (par[v] == v) { // Если элемент ссылается на самого себя, то это корень, следовательно это искомый ответ
  11.         return v; // возвращаем искомый ответ
  12.     }
  13.     // Одновременно находим корень блока (он в виде дерева), к которому принадлежит предок v и напрямую подвешиваем к этому корню v
  14.     return par[v] = get_par(par[v]);
  15. }
  16.  
  17. void unite(int a, int b) { // функция, объединяющая 2 блока
  18.     a = get_par(a); // находим корень блока, к которому принадлежит a-ое место
  19.     b = get_par(b); // находим корень множества, к которому принадлежит b-ое место
  20.     if (a == b) return; // Если корни блоков равны, то это означает, что блоки уже объединены
  21.     if (sz[a] > sz[b]) // Если размер блока, в котором корень a, больше размера блока, в котором корень b, то меняем значения в a и b
  22.         swap(a, b);
  23.     par[a] = b; // подвешиваем a к b
  24.     sz[b] += sz[a]; // Увеличиваем размер блока с корнем b на размер блока с корнем a
  25.     gm[b] = max(gm[b], gm[a]); // максимальный номер места, принадлежащего b-ому блоку - это максимум из текущего максимального значения и максимального значения у a-го блока
  26. }
  27.  
  28. void solve() {
  29.     int n;
  30.     cin >> n; // считываем кол-во мест на парковке
  31.     vector<int> ans(n, -1); // ans[i] = j означает, что i-ая машина встала на j-ое место
  32.     vector<bool> free(n, true); // free[i] = true, если i-ое место свободно
  33.                                 // free[i] = false, если i-ое место занято
  34.     sz.resize(n, 1); // изначально размер каждого блока равен 1, так как все блоки состоят из 1-ой места
  35.     par.resize(n);
  36.     // изначально каждый блок состоит из 1-го места, которое является корнем, поэтому ссылается на самого себя
  37.     for (int i = 0; i < n; ++i) {
  38.         par[i] = i;
  39.     }
  40.     gm.resize(n); // изначально каждый блок состоит из 1-го места, номер которого является максимальным во всём блоке
  41.     for (int i = 0; i < n; ++i) {
  42.         gm[i] = i;
  43.     }
  44.     for (int i = 0; i < n; ++i) {
  45.         int idx;
  46.         cin >> idx; // считываем номер места, на которое машина планирует встать
  47.         idx--; // уменьшаем номер места на 1, так как в задаче нумерация идёт с 1, а нам выгоднее, если нумерация будет с 0
  48.         if (free[idx]) { // Если место и так свободно, то просто ставим машину туда (помечаем, что место занято)
  49.             ans[i] = idx; // Указываем, что i-ая машина встаёт на idx-ое место
  50.         } else if (gm[get_par(idx)] < n - 1) { // Если блок, содержащий idx-ое место заканчивается раньше (n - 1)-го места, то машина встанет на 1-ое место после этого блока
  51.             ans[i] = gm[get_par(idx)] + 1;
  52.         } else if (free[0]) { // Если блок, содержащий idx-ое место заканчивается в (n - 1)-ом месте, а 0-ое место свободно, то машина встанет на это свободное место
  53.             ans[i] = 0;
  54.         } else { // Если блок, содержащий idx-ое место заканчивается в (n - 1)-ом месте, а 0-ое место занято, то машина встанет на 1-ое место после блока, содержащего 0-ое место
  55.             ans[i] = gm[get_par(0)] + 1;
  56.         }
  57.         free[ans[i]] = false; // Указываем, что место, на которое встанет i-ая машина теперь занято
  58.         if (ans[i] - 1 >= 0 && !free[ans[i] - 1]) { // Если слева от места, на которое встала машина, есть занятый блок, и место слева не "через границу" (Левое число не должно иметь вид n - 1), то объединяем ans[i]-ое место с левым блоком.
  59.             unite(ans[i] - 1, ans[i]);
  60.         }
  61.         if (ans[i] + 1 < n && !free[ans[i] + 1]) { // Если справа от места, на которое встала машина, есть занятый блок, и место справа не "через границу" (Правое число не должно быть равно 0), то объединяем ans[i]-ое место с правым блоком.
  62.             unite(ans[i], ans[i] + 1);
  63.         }
  64.     }
  65.     for (auto el : ans) { // выводим ответы
  66.         cout << el + 1 <<  ' '; // к каждому ответу нужно прибавить 1, так как в задаче нумерация идёт с 1, а в коде с 0
  67.     }
  68. }
  69.  
  70. int main() {
  71.     solve();
  72.     return 0;
  73. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement