Cod sursa(job #1451395)

Utilizator Dddarius95Darius-Florentin Neatu Dddarius95 Data 16 iunie 2015 21:59:47
Problema Heapuri Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 6.16 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstdlib>
using namespace std;
ifstream f("heapuri.in");
ofstream g("heapuri.out");

template <typename T>
struct TreapNode{
    T* key;
    int priority; 
    TreapNode *left, *right, *parent;
    int noOfNodes;

    TreapNode() {
      key = NULL;
      priority = -1;
      left = right = NULL;
      parent = NULL;
      noOfNodes = 1;
    }

    ~TreapNode() {
      if (key) delete key;
      if (left) delete left;
      if (right) delete right;
    }

    TreapNode<T> *find(const T& newkey) {
      if (key == NULL) {
        return NULL;
      }
      
      if (*key == newkey) {
        return this;
      }

      if (newkey < *key) {
        if (left) return left->find(newkey);
      } else {
        if (right) return right->find(newkey);
      }

      return NULL;
    }

    TreapNode<T>  *rotateRight() {
      TreapNode<T> *a, *b, *c, *w, *z, *gf = NULL;

      w = this;
      a = left;
      b = right;
      z = parent;
      c = parent->right;
      if (z) gf = z->parent;

      int ka = 0, kb= 0, kc = 0, kw = w->noOfNodes, kz = z->noOfNodes;
      if (a) ka = a->noOfNodes;
      if (b) kb = b->noOfNodes;
      if (c) kc = c->noOfNodes;
      z->noOfNodes = kb + kc + 1;
      w->noOfNodes = ka + kb + kc + 2;

      w->parent = gf;
      if (gf) {
        if (gf->left == z) gf->left = w;
        else gf->right = w;
      }

      w->right = z;
      z->parent = w;

      z->left = b;
      if (b) b->parent = z;

      return w;
    }

    TreapNode<T>  *rotateLeft() {
      TreapNode<T> *a, *b, *c, *w, *z, *gf = NULL;

      z = this;
      b = left;
      c = right;
      w = parent;
      a = parent->left;
      if (w) gf = w->parent;

      int ka = 0, kb= 0, kc = 0, kw = w->noOfNodes, kz = z->noOfNodes;
      if (a) ka = a->noOfNodes;
      if (b) kb = b->noOfNodes;
      if (c) kc = c->noOfNodes;
      w->noOfNodes = ka + kb + 1;
      z->noOfNodes = ka + kb + kc + 2;

      z->parent = gf;
      if (gf) {
        if (gf->left == w) gf->left = z;
        else gf->right = z;
      }

      z->left = w;
      w->parent = z;

      w->right = b;
      if (b) b->parent = w;

      return z;
    }

    void pushUp(TreapNode<T> *node) {

      while (node->parent && node->priority < node->parent->priority) {

        if (node->parent->left == node) {
          node->rotateRight();
        } else {
          node->rotateLeft();
        }
      }

    }

    void pushDown(TreapNode<T> *node) {

      while (node->left || node->right) {
        int p1 = -1, p2 = -1;
        if (node->left) p1 = node->left->priority;
        if (node->right) p2 = node->right->priority;
        if (p1 > p2) {
          node->left->rotateRight();
        } else {
          node->right->rotateLeft();
        }
      }


    }

    void insert(const T& newkey, const int& newpriority) {
      ++noOfNodes;
      if (key == NULL) {
        key = new T;
        *key = newkey;
        priority = newpriority;

        pushUp(this);

        return;
      }
      
      if (newkey < *key) {
        if (left == NULL) {
          left = new TreapNode<T>();
          left->parent = this;
        }
        left->insert(newkey, newpriority);
      } else {
        if (right == NULL) {
          right = new TreapNode<T>();
          right->parent = this;
        }
        right->insert(newkey, newpriority);
      }

    }

    TreapNode<T>* remove(TreapNode<T> *node) {
      // Check if is root and hasn't any child.
      --noOfNodes;
      if (node == this) {
        if (left == NULL && right == NULL) {
          delete node;
          return NULL;
        } 
      }


      
      pushDown(node);
      
      TreapNode<T> *newroot = node;
      while(newroot->parent) {
        newroot = newroot->parent;
      }

      removeLeaf(node);
      return newroot;
    }

    void removeLeaf(TreapNode<T> *node) {
      if (node->parent->left == node) {
        node->parent->left = NULL;
      } else {
        node->parent->right = NULL;
      }
      delete node;
    }

    void inOrder() {
      if (left) left->inOrder();
      std::cout << *key << ' ';
      if (right) right->inOrder();
    }

    void preOrder() {
      std::cout << priority << ' ';
      if (left) left->preOrder();
      if (right) right->preOrder();
    }

    TreapNode<T> *findK(int& k) {
      if (k > noOfNodes) {
        return NULL;
      }


      if (left && k <= left->noOfNodes) {
        return left->findK(k);
      } 
      
      k -= left->noOfNodes;

      if (k == 1) return this;

      k--; 
      
      if(right) {
        return right->findK(k);
      }
      
      return NULL;
    }
};

template <typename T>
class Treap{
  private:
    TreapNode<T> *root;
  public:
    Treap() {
      root = NULL;
      srand(time(NULL));
    }

    ~Treap() {
      if (root) delete root;
    }

    void insert(const T& key, unsigned int newpriority = -1) {
      if (root == NULL) {
        root = new TreapNode<T>();
      }
      int priority = ( (newpriority != -1) ? newpriority : rand() ) ;
      root->insert(key, priority);
    }

    bool find(const T& key) {
      if (root == NULL) return false;
      return root->find(key) != NULL;
    }

    void remove(const T& key) {
      if (root == NULL) return;
      TreapNode<T> *node = root->find(key);
      if (node) {
        root = root->remove(node);
      }
    }

    void display() {
      if (root) {
        root->inOrder();
        std::cout << '\n';
      }
    }

    unsigned int size() {
      return root->noOfNodes;
    }

    T& findK(T& k) {
      TreapNode<T> *node = root->findK(k);
      if (node) {
        return *node->key;
      }
    }

    unsigned int min() {
      return root->priority;
    }
};


Treap <int> T;
int N, x, op, cnt;

int main() {
  f >> N;
  for (int i = 1; i <= N; i++) {
    
    
    f >> op;
    //g << "------------ " << i << "=>" << op << '\n';
    switch (op) {
      case 1: 
        f >> x;
        T.insert(++cnt, x);
        break;
      case 2:
        f >> x;
        T.remove(x);
        break;
      case 3:
        g << T.min() << '\n';
        break;
      default:
        break;
    }

    //T.display();
    //g << "------------ \n" ;
  }

  f.close();
  g.close();


  return 0;
}