Advertisement
Guest User

treap

a guest
Jul 21st, 2018
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.86 KB | None | 0 0
  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <algorithm>
  4. #include <ctime>
  5.  
  6. class Treap {
  7. private:
  8.     class Node {
  9.         //copyConstruct и т.д.
  10.     public:
  11.         long long element;
  12.  
  13.         bool reversed; //для next-prev
  14.         long long sum; //уже насчитано на подотрезке
  15.         long long add; //надо добавить
  16.         //addFlag?
  17.         long long assign;
  18.         bool assignFlag;
  19.  
  20.         bool isIncreasing; //строго?
  21.         bool isDecreasing;
  22.         long long leftmost; //крайний левый
  23.         long long rightmost; //крайний правый
  24.  
  25.         long long weight; //для неявного
  26.         long long priority;
  27.  
  28.         Node * left;
  29.         Node * right;
  30.  
  31.         Node(int x) : element(x), reversed(false), sum(x), add(0), assign(0), assignFlag(false),
  32.             isIncreasing(true), isDecreasing(true), leftmost(x), rightmost(x), weight(1), priority(rand()),
  33.             left(nullptr), right(nullptr) {}
  34.         ~Node() {
  35.             left = right = nullptr;
  36.         }
  37.  
  38.  
  39.         void updateSuffixInf() {
  40.             if (this == nullptr) return;
  41.  
  42.             if (left == nullptr && right == nullptr) {
  43.                 isDecreasing = true;
  44.                 isIncreasing = true;
  45.                 leftmost = rightmost = element;
  46.                 return;
  47.             }
  48.  
  49.             if (left == nullptr) {
  50.                 if (right->isDecreasing && element >= right->leftmost) isDecreasing = true;
  51.                 else isDecreasing = false;
  52.  
  53.                 if (right->isIncreasing && element <= right->leftmost) isIncreasing = true;
  54.                 else isIncreasing = false;
  55.  
  56.                 leftmost = element;
  57.                 rightmost = right->rightmost;
  58.             }
  59.             else if (right == nullptr) {
  60.                 if (left->isDecreasing && element <= left->rightmost) isDecreasing = true;
  61.                 else isDecreasing = false;
  62.  
  63.                 if (left->isIncreasing && element >= left->rightmost) isIncreasing = true;
  64.                 else isIncreasing = false;
  65.  
  66.                 leftmost = left->leftmost;
  67.                 rightmost = element;
  68.             }
  69.             else {
  70.                 if (left->isDecreasing && right->isDecreasing && left->rightmost >= element && element >= right->leftmost) isDecreasing = true;
  71.                 else isDecreasing = false;
  72.                 if (left->isIncreasing && right->isIncreasing && left->rightmost <= element && element <= right->leftmost) isIncreasing = true;
  73.                 else isIncreasing = false;
  74.  
  75.                 leftmost = left->leftmost;
  76.                 rightmost = right->rightmost;
  77.             }
  78.  
  79.         }
  80.  
  81.  
  82.         long long getWeight() const {
  83.             if (this == nullptr) return 0;
  84.             else return this->weight;
  85.         }
  86.         void updateWeight() {
  87.             weight = left->getWeight() + right->getWeight() + 1;
  88.         }
  89.  
  90.         long long getSum() const {
  91.             if (this == nullptr) return 0;
  92.             return sum;
  93.         }
  94.         void updateSum() {
  95.             sum = element + left->getSum() + right->getSum();
  96.         }
  97.  
  98.         void pushAssign() {
  99.             if (this == nullptr) return;
  100.  
  101.             if (!assignFlag) return;
  102.             element = assign;
  103.             sum = assign * this->getWeight();
  104.             leftmost = rightmost = assign;
  105.             isIncreasing = isDecreasing = true;
  106.  
  107.             assignFlag = false;
  108.             if (left != nullptr) {
  109.                 left->assign = assign;
  110.                 left->assignFlag = true;
  111.             }
  112.             if (right != nullptr) {
  113.                 right->assign = assign;
  114.                 right->assignFlag = true;
  115.             }
  116.         }
  117.  
  118.         void pushAdd() {
  119.             if (this == nullptr) return;
  120.  
  121.             element += add;
  122.             leftmost += add;
  123.             rightmost += add;
  124.             sum += add * this->getWeight();
  125.  
  126.             if (left != nullptr) {
  127.                 left->add += add;
  128.             }
  129.             if (right != nullptr) {
  130.                 right->add += add;
  131.             }
  132.  
  133.             add = 0;
  134.         }
  135.         void pushReversed() {
  136.             if (this == nullptr) return;
  137.             if (!reversed) return;
  138.  
  139.             std::swap(isDecreasing, isIncreasing);//??????????
  140.             std::swap(leftmost, rightmost);
  141.             std::swap(left, right);
  142.  
  143.             reversed = false;
  144.             if (left != nullptr) left->reversed ^= true;
  145.             if (right != nullptr) right->reversed ^= true;
  146.         }
  147.     };
  148.  
  149.     long long findIndForNext(Node * n) {
  150.         if (n == nullptr) return 0;
  151.         globalPush(n);
  152.  
  153.         if (n->right != nullptr && !n->right->isDecreasing) {
  154.             return n->left->getWeight() + 1 + findIndForNext(n->right);
  155.         }
  156.         if (n->right != nullptr && n->element < n->right->leftmost) {
  157.             return n->left->getWeight() + 1;
  158.         }
  159.         if (n->left != nullptr && n->element > n->left->rightmost) {
  160.             return n->left->getWeight();
  161.         }
  162.         return findIndForNext(n->left);
  163.     }
  164.  
  165.     long long findIndForPrev(Node * n) {
  166.         if (n == nullptr) return 0;
  167.         globalPush(n);
  168.  
  169.         if (n->right != nullptr && !n->right->isIncreasing) {
  170.             return n->left->getWeight() + 1 + findIndForPrev(n->right);
  171.         }
  172.         if (n->right != nullptr && n->element > n->right->leftmost) {
  173.             return n->left->getWeight() + 1;
  174.         }
  175.         if (n->left != nullptr && n->element < n->left->rightmost) {
  176.             return n->left->getWeight();
  177.         }
  178.         return findIndForPrev(n->left);
  179.     }
  180.  
  181.  
  182.     void recalc(Node * n) {
  183.         if (n == nullptr) return;
  184.         globalPush(n);
  185.  
  186.         n->updateWeight();
  187.         n->updateSum();
  188.         n->updateSuffixInf();
  189.     }
  190.     void pushAll(Node * n) {
  191.         if (n == nullptr) return;
  192.  
  193.         n->pushReversed();
  194.         n->pushAdd();
  195.         n->pushAssign();
  196.     }
  197.  
  198.     void globalPush(Node * n) {
  199.         if (n == nullptr) return;
  200.         pushAll(n);
  201.         pushAll(n->left);
  202.         pushAll(n->right);
  203.  
  204.         //add
  205.         if (n->left != nullptr) {
  206.             pushAll(n->left->left);
  207.             pushAll(n->left->right);
  208.         }
  209.         if (n->right != nullptr) {
  210.             pushAll(n->right->left);
  211.             pushAll(n->right->right);
  212.         }
  213.     }
  214.  
  215.     //[key)
  216.     void splitByKey(Node * node, int key, Node * &l, Node * &r) {
  217.  
  218.         if (node == nullptr) {
  219.             l = r = nullptr;
  220.             return;
  221.         }
  222.         globalPush(node);
  223.  
  224.         if (node->element > key) {
  225.             splitByKey(node->right, key, node->right, r);
  226.             l = node;
  227.             recalc(l);
  228.         }
  229.         else {
  230.             splitByKey(node->left, key, l, node->left);
  231.             r = node;
  232.             recalc(r);
  233.         }
  234.     }
  235.  
  236.     //[)key
  237.     std::pair <Node *, Node *> split(Node * node, int key) {
  238.         pushAll(node);
  239.  
  240.         std::pair<Node*, Node*> result;
  241.  
  242.         if (node == nullptr) {
  243.             result = std::make_pair(nullptr, nullptr);
  244.         }
  245.  
  246.         if (node->left->getWeight() + 1 <= key) {
  247.             std::pair <Node *, Node *> splitR = split(node->right, key - node->left->getWeight() - 1);
  248.             node->right = splitR.first;
  249.             recalc(node);
  250.             result = std::make_pair(node, splitR.second);
  251.         }
  252.         else {
  253.             std::pair <Node *, Node *> splitL = split(node->left, key);
  254.             node->left = splitL.second;
  255.             recalc(node);
  256.             result = std::make_pair(splitL.first, node);
  257.         }
  258.        
  259.         return result;
  260.     }
  261.     Node * merge(Node * l, Node * r) {
  262.  
  263.         if (l == nullptr) return r;
  264.         if (r == nullptr) return l;
  265.  
  266.         if (l->priority < r->priority) {
  267.             r->left = merge(l, r->left);
  268.             recalc(r);
  269.             return r;
  270.         }
  271.         else {
  272.             l->right = merge(l->right, r);
  273.             recalc(l);
  274.             return l;
  275.         }
  276.     }
  277.  
  278.     //обход
  279.     void inOrder(Node * n) {
  280.         if (n == nullptr) return;
  281.  
  282.         globalPush(n);
  283.  
  284.         inOrder(n->left);
  285.         std::cout << n->element << " ";
  286.         inOrder(n->right);
  287.     }
  288.     //удаление
  289.     void postOrder(Node * n) {
  290.         if (n == nullptr) return;
  291.  
  292.         postOrder(n->left);
  293.         postOrder(n->right);
  294.         delete n->left;
  295.         delete n->right; //??
  296.     }
  297.  
  298.  
  299.     Node * root;
  300.  
  301.  
  302. public:
  303.     Treap() : root(nullptr) {}
  304.     //~Treap() ?? destruct all by postOrder
  305.  
  306.     void printTreap() {
  307.         inOrder(root);
  308.     }
  309.  
  310.     void insertOnPos(long long ind, long long x) {
  311.         Node * newNode = new Node(x);
  312.         std::pair <Node *, Node *> spl = split(root, ind);
  313.         root = merge(merge(spl.first, newNode), spl.second);
  314.     }
  315.  
  316.     long long getSumOnSubsegment(long long lInd, long long rInd) {
  317.         long long ans;
  318.         std::pair <Node *, Node *> rightPart = split(root, rInd + 1);
  319.         std::pair <Node *, Node *> leftPart = split(rightPart.first, lInd);
  320.         ans = leftPart.second->getSum();
  321.         root = merge(merge(leftPart.first, leftPart.second), rightPart.second);
  322.  
  323.         return ans;
  324.     }
  325.  
  326.     void deleteOnPos(long long ind) {
  327.         std::pair <Node *, Node *> rightPart = split(root, ind + 1);
  328.         std::pair <Node *, Node *> leftPart = split(rightPart. first, ind);
  329.         delete leftPart.second;
  330.         root = merge(leftPart.first, rightPart.second);
  331.     }
  332.  
  333.     void assignOnSubsegment(long long x, long long lInd, long long rInd) {
  334.         std::pair <Node *, Node *> rightPart = split(root, rInd + 1);
  335.         std::pair <Node *, Node *> leftPart = split(rightPart.first, lInd);
  336.  
  337.         globalPush(leftPart.second);
  338.  
  339.         leftPart.second->assignFlag = true;
  340.         leftPart.second->assign = x;
  341.         //center->pushAssign();
  342.  
  343.         globalPush(leftPart.second);
  344.  
  345.         root = merge(merge(leftPart.first, leftPart.second), rightPart.second);
  346.     }
  347.  
  348.     void addOnSubSegment(long long x, long long lInd, long long rInd) {
  349.         std::pair <Node *, Node *> rightPart = split(root, rInd + 1);
  350.         std::pair <Node *, Node *> leftPart = split(rightPart.first, lInd);
  351.  
  352.         globalPush(leftPart.second);
  353.  
  354.         leftPart.second->add += x;
  355.         //center->pushAdd();
  356.  
  357.         globalPush(leftPart.second);
  358.  
  359.         root = merge(merge(leftPart.first, leftPart.second), rightPart.second);
  360.     }
  361.  
  362.     void nextPermutation(long long lInd, long long rInd) {
  363.         Node *l, *r, *center;
  364.  
  365.         split(root, rInd + 1, l, r);
  366.         split(l, lInd, l, center);
  367.         globalPush(center);
  368.         long long startInd = findIndForNext(center);
  369.  
  370.         if (startInd == 0) {
  371.             center->reversed = true;
  372.             /*center->pushReversed();
  373.  
  374.             center->left->pushReversed();
  375.             center->right->pushReversed();*/
  376.  
  377.             globalPush(center);
  378.  
  379.             root = merge(l, merge(center, r));
  380.             return;
  381.         }
  382.  
  383.         Node * suffix, *swapElementC, *swapElementS, *suffixRight;
  384.         split(center, startInd, center, suffix);
  385.         split(center, center->getWeight() - 1, center, swapElementC);
  386.  
  387.         splitByKey(suffix, swapElementC->element, suffix, suffixRight);
  388.         split(suffix, suffix->getWeight() - 1, suffix, swapElementS);
  389.  
  390.         suffix = merge(suffix, swapElementC);
  391.         center = merge(center, swapElementS);
  392.         suffix = merge(suffix, suffixRight);
  393.  
  394.         suffix->reversed = true;
  395.         /*suffix->pushReversed();
  396.         suffix->left->pushReversed();
  397.         suffix->right->pushReversed();*/
  398.  
  399.         globalPush(suffix);
  400.  
  401.         root = merge(l, merge(merge(center, suffix), r));
  402.     };
  403.  
  404.     void prevPermutation(long long lInd, long long rInd) {
  405.         Node *l, *r, *center;
  406.         split(root, rInd + 1, l, r);
  407.         split(l, lInd, l, center);
  408.         globalPush(center);
  409.         long long startInd = findIndForPrev(center);
  410.  
  411.         if (startInd == 0) {
  412.             center->reversed = true;
  413.             /*center->pushReversed();
  414.             center->left->pushReversed();
  415.             center->right->pushReversed();*/
  416.  
  417.             globalPush(center);
  418.  
  419.             root = merge(l, merge(center, r));
  420.             return;
  421.         }
  422.  
  423.         Node * suffix, *swapElementC, *swapElementS, *suffixRight;
  424.         split(center, startInd, center, suffix);
  425.         split(center, center->getWeight() - 1, center, swapElementC);
  426.  
  427.         suffix->reversed = true;
  428.         /*suffix->pushReversed();
  429.         suffix->left->pushReversed();
  430.         suffix->right->pushReversed();*/
  431.  
  432.         globalPush(suffix);
  433.  
  434.         splitByKey(suffix, swapElementC->element, suffix, suffixRight);
  435.         split(suffixRight, 1, swapElementS, suffixRight);
  436.  
  437.         suffixRight = merge(swapElementC, suffixRight);
  438.         center = merge(center, swapElementS);
  439.         suffix = merge(suffix, suffixRight);
  440.  
  441.         root = merge(l, merge(merge(center, suffix), r));
  442.     }
  443. };
  444.  
  445.  
  446. int main() {
  447.     srand(time(0));
  448.  
  449.     long long n, q;
  450.     long long x, l, r;
  451.     long long comand, pos;
  452.     std::cin >> n;
  453.     Treap treap;
  454.    
  455.     //start tree
  456.     for (long long i = 0; i < n; ++i) {
  457.         std::cin >> x;
  458.         treap.insertOnPos(i, x);
  459.     }
  460.  
  461.  
  462.     std::cin >> q;
  463.     for (long long i = 0; i < q; ++i) {
  464.         std::cin >> comand;
  465.         if (comand == 1) {
  466.             std::cin >> l >> r;
  467.             std::cout << treap.getSumOnSubsegment(l, r) << std::endl;
  468.         }
  469.         else if (comand == 2) {
  470.             std::cin >> x >> pos;
  471.             treap.insertOnPos(pos, x);
  472.             //treap.printTreap();
  473.         }
  474.         else if (comand == 3) {
  475.             std::cin >> pos;
  476.             treap.deleteOnPos(pos);
  477.             //treap.printTreap();
  478.         }
  479.         else if (comand == 4) {
  480.             std::cin >> x >> l >> r;
  481.             treap.assignOnSubsegment(x, l, r);
  482.             //treap.printTreap();
  483.         }
  484.         else if (comand == 5) {
  485.             std::cin >> x >> l >> r;
  486.             treap.addOnSubSegment(x, l, r);
  487.             //treap.printTreap();
  488.         }
  489.         else if (comand == 6) {
  490.             std::cin >> l >> r;
  491.             treap.nextPermutation(l, r);
  492.             //treap.printTreap();
  493.             //std::cout << std::endl;
  494.         }
  495.         else if (comand == 7) {
  496.             std::cin >> l >> r;
  497.             treap.prevPermutation(l, r);
  498.             //treap.printTreap();
  499.             //std::cout << std::endl;
  500.         }
  501.     }
  502.     treap.printTreap();
  503.     return 0;
  504. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement