Advertisement
he_obviously

treap_RMQ

Jul 12th, 2020
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.56 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4. #include <queue>
  5. #include <set>
  6. #include <iomanip>
  7. #include <map>
  8. #include <algorithm>
  9. #include <cmath>
  10. #include <bitset>
  11. #include <limits.h>
  12.  
  13. using namespace std;
  14.  
  15. typedef long long ll;
  16. typedef long double ld;
  17.  
  18. #define all(x) (x).begin(),(x).end()
  19. #define pii pair<int, int>
  20. #define sz(x) (int)x.size()
  21.  
  22. struct Node {
  23. //val - значение в вершине, y - рандомный приоритет,
  24. //size - размер обоих поддеревьев + 1 (сама вершина),
  25. //min - минимум в вершине и обоих её поддеревьях
  26.     int val, y, size, min;
  27.     Node* left; Node* right;
  28.     Node(int v) {
  29.         this->val = this->min = v;
  30.         this->size = 1;
  31.         this->y = (rand() << 15) + rand();
  32. //сдвиг делаю, потому что rand() до 32767, а надо, чтобы было поменьше одинаковых приоритетов
  33.         this->left = this->right = NULL;
  34.     }
  35. };
  36.  
  37. //если указатель нулевой (NULL), то программа упадёт, если пытаться внутри него к чему-то обратиться
  38. //поэтому случай нулевого указателя в ДД всегда разбирается отдельно и в начале
  39.  
  40. int get_min(Node* v) { return v == NULL ? INT_MAX : v->min; }
  41.  
  42. int get_size(Node* v) { return v == NULL ? 0 : v->size; }
  43.  
  44. //после сплитов и мерджей могли измениться дети => надо обновить информацию об их родителе
  45. void update(Node* v) {
  46.     if (v == NULL) return;
  47.     v->size = get_size(v->left) + get_size(v->right) + 1;
  48.     v->min = min(v->val, min(get_min(v->left), get_min(v->right)));
  49. }
  50.  
  51. //сливает два дерева
  52. Node* merge(Node* f, Node* s) {
  53.     if (f == NULL) return s;
  54.     if (s == NULL) return f;
  55. //если f будет вершиной итогового дерева, то так как оно стоит слева от s
  56. //(потому что на merge мы всегда вводим сначала дерево, которое стоит слева, а потом справа)
  57. //его левый ребенок никак не изменится, а правый будет сливаться с s - это и делаем
  58.     if (f->y > s->y) {
  59.         f->right = merge(f->right, s);
  60.         update(f);
  61.         return f;
  62.     }
  63. //аналогично, если s оказалось вершиной итогового дерева, то его правый сын никак не
  64. //изменится, а левый придётся сливать с f - это и делаем
  65.     else {
  66.         s->left = merge(f, s->left);
  67.         update(s);
  68.         return s;
  69.     }
  70. }
  71.  
  72. //здесь размышляем как "отрезать первые k элементов",
  73. //тогда первый элемент пары - вершина ДД из первых k элементов,
  74. //второй - вершина ДД с оставшимися элементами
  75. pair<Node*, Node*> split_kth(Node* v, int k) {
  76.     if (v == NULL) return { NULL, NULL };
  77. //если в левом сыне не меньше k элементов, то именно его придётся резать, а
  78. //правый сын и изначальная вершина останутся нетронутыми.
  79. //когда мы разрезали левого ребёнка, надо прицепить к изначальной вершине тот обрубок,
  80. //который остался после k элементов
  81.     if (k <= get_size(v->left)) {
  82.         auto res = split_kth(v->left, k);
  83.         v->left = res.second;
  84.         update(v);
  85.         return { res.first, v };
  86.     }
  87. //те же размышления (я заебался писать просто уже немного)
  88.     else {
  89.         auto res = split_kth(v->right, k - get_size(v->left) - 1);
  90.         v->right = res.first;
  91.         update(v);
  92.         return { v, res.second };
  93.     }
  94. }
  95.  
  96. //обрубили первые i элементов, присобачили посередине новый элемент и слили всё обратно
  97. Node* insert(Node* v, int i, int x) {
  98.     Node* elem = new Node(x);
  99.     auto res = split_kth(v, i);
  100.     return merge(res.first, merge(elem, res.second));
  101. }
  102.  
  103. //обрубили кусок [l...r] (сначала отхерачили первые l-1, потом от второго куска ещё r-l+1)
  104. //на этом куске в вершине уже будет храниться минимум (потому что в сплитах и мерджах мы делали обновления)
  105. //запомнили ответ, соединили всё обратно и вернули ответ
  106. int get_min(Node* v, int l, int r) {
  107.     auto res1 = split_kth(v, l - 1);
  108.     auto res2 = split_kth(res1.second, r - l + 1);
  109.     int ans = res2.first->min;
  110.     merge(res1.first, merge(res2.first, res2.second));
  111.     return ans;
  112. }
  113.  
  114. int main() {
  115.  
  116.     ios_base::sync_with_stdio(0);
  117.     cin.tie(0); cout.tie(0);
  118.  
  119.     int n;
  120.     cin >> n;
  121.  
  122.     Node* root = NULL;
  123.  
  124.     for (int i = 0; i < n; ++i) {
  125.         char x;
  126.         cin >> x;
  127.         if (x == '+') {
  128.             int i, x;
  129.             cin >> i >> x;
  130.             root = insert(root, i, x);
  131.         }
  132.         else {
  133.             int l, r;
  134.             cin >> l >> r;
  135.             cout << get_min(root, l, r) << "\n";
  136.         }
  137.     }
  138.  
  139.     return 0;
  140. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement