Matrix_code

data-structure - Explicit Treap

Mar 27th, 2020 (edited)
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.25 KB | None | 0 0
  1. /*
  2. Codeforces 702F
  3. Solution: https://codeforces.com/blog/entry/46324?#comment-307625
  4. Complexity: NlogK + KlogKlog10^9
  5. */
  6. #include <bits/stdc++.h>
  7. using namespace std;
  8.  
  9. const int N = 2e5 + 5;
  10. struct item {
  11.   int c, q;
  12.   bool operator<(const item &rhs) const {
  13.     if (q == rhs.q)
  14.       return c < rhs.c;
  15.     return q > rhs.q;
  16.   }
  17. };
  18.  
  19. struct node {
  20.   node *left, *right;
  21.   unsigned int pri;
  22.   int val, lazyVal;
  23.   int sum, lazySum;
  24.   int id;
  25. };
  26. unsigned int genPri() {
  27.   unsigned int x = rand();
  28.   unsigned int y = rand();
  29.   return (x << 16) | y;
  30. }
  31. node *reassign(node *n, node *l, node *r, int pri, int val, int sum, int id) {
  32.   n->left = l, n->right = r;
  33.   n->pri = pri;
  34.   n->val = val, n->lazyVal = 0;
  35.   n->sum = sum, n->lazySum = 0;
  36.   n->id = id;
  37.   return n;
  38. }
  39.  
  40. node *reassign(node *n, node *l, node *r) {
  41.   return reassign(n, l, r, n->pri, n->val, n->sum, n->id);
  42. }
  43.  
  44. void apply(node *n, int lazyVal, int lazySum) {
  45.   n->val += lazyVal;
  46.   n->lazyVal += lazyVal;
  47.   n->sum += lazySum;
  48.   n->lazySum += lazySum;
  49. }
  50. void down(node *n) {
  51.   if (n->left)
  52.     apply(n->left, n->lazyVal, n->lazySum);
  53.   if (n->right)
  54.     apply(n->right, n->lazyVal, n->lazySum);
  55.   n->lazyVal = 0;
  56.   n->lazySum = 0;
  57. }
  58. node *getLeft(node *n) {
  59.   while (n->left)
  60.     down(n), n = n->left;
  61.   return n;
  62. }
  63.  
  64. node *getRight(node *n) {
  65.   while (n->right)
  66.     down(n), n = n->right;
  67.   return n;
  68. }
  69.  
  70. // {<, >=}
  71. pair<node *, node *> split(node *n, int k) {
  72.   if (!n)
  73.     return {nullptr, nullptr};
  74.   down(n);
  75.   node *l, *r;
  76.   if (n->val < k) {
  77.     tie(l, r) = split(n->right, k);
  78.     reassign(n, n->left, l);
  79.     return {n, r};
  80.   }
  81.   tie(l, r) = split(n->left, k);
  82.   reassign(n, r, n->right);
  83.   return {l, n};
  84. }
  85.  
  86. node *merge(node *l, node *r) {
  87.   if (!l || !r)
  88.     return l ? l : r;
  89.   down(l);
  90.   down(r);
  91.   if (l->pri < r->pri)
  92.     return reassign(l, l->left, merge(l->right, r));
  93.   return reassign(r, merge(l, r->left), r->right);
  94. }
  95.  
  96. node *ins(node *root, node *n) {
  97.   node *l, *r;
  98.   tie(l, r) = split(root, n->val);
  99.   return merge(l, merge(n, r));
  100. }
  101.  
  102. int ans[N];
  103. void traverse(node *root) {
  104.   if (!root)
  105.     return;
  106.   ans[root->id] = root->sum;
  107.   down(root);
  108.   traverse(root->left);
  109.   traverse(root->right);
  110. }
  111.  
  112. int main() {
  113.   int n, k;
  114.   scanf("%d", &n);
  115.   item items[n];
  116.   for (int i = 0; i < n; i++)
  117.     scanf("%d %d", &items[i].c, &items[i].q);
  118.   sort(items, items + n);
  119.  
  120.   node *root = nullptr;
  121.   scanf("%d", &k);
  122.   for (int i = 0; i < k; i++) {
  123.     int x;
  124.     scanf("%d", &x);
  125.     node *cur = reassign(new node(), nullptr, nullptr, genPri(), x, 0, i);
  126.     if (!root)
  127.       root = cur;
  128.     else
  129.       root = ins(root, cur);
  130.   }
  131.  
  132.   for (auto item : items) {
  133.     node *l, *r;
  134.     tie(l, r) = split(root, item.c);
  135.     if (!r)
  136.       continue;
  137.     apply(r, -item.c, 1);
  138.     if (!l) {
  139.       root = r;
  140.       continue;
  141.     }
  142.  
  143.     node *rl = getLeft(r), *lr = getRight(l);
  144.     while (rl->val < lr->val) {
  145.       node *tl, *tr;
  146.       tie(tl, tr) = split(r, rl->val + 1);
  147.       l = ins(l, tl);
  148.       r = tr;
  149.       if (!l || !r)
  150.         break;
  151.       rl = getLeft(r);
  152.       lr = getRight(l);
  153.     }
  154.     root = merge(l, r);
  155.   }
  156.   traverse(root);
  157.   for (int i = 0; i < k; i++)
  158.     printf("%d ", ans[i]);
  159.   return 0;
  160. }
Add Comment
Please, Sign In to add comment