#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <cstdlib>
#include<algorithm>
using namespace std;
template <class elem>
class priorityqueue
{
private:
struct node
{
node* left;
node* right;
elem data;
int npl;
node(node* left_i, node* right_i, elem data_i, int npl_i) :left(left_i), right(right_i), data(data_i), npl(npl_i) {}
};
node* root;
int currentsize;
public:
node* getroot()
{
return root;
}
void setroot(node* p)
{
root = p;
}
int size()
{
return currentsize;
}
void setsize(int k)
{
currentsize = k;
}
priorityqueue()
{
currentsize = 0;
root = NULL;
}
priorityqueue(node* p, int size)
{
currentsize = size;
root = p;
}
priorityqueue(elem data)
{
currentsize = 1;
root = new node(NULL, NULL, data, 0);
}
void deletedata(node* &root)
{
if (root->left != NULL)
deletedata(root->left);
if (root->right != NULL)
deletedata(root->right);
delete root;
root = NULL;
}
~priorityqueue()
{
deletedata(root);
}
void swap(node* p)
{
node* tmp = p->left;
p->left = p->right;
p->right = tmp;
}
void enqueue(elem data)
{
node* p = new node(NULL, NULL, data, 0);
root = merge(root, p);
currentsize++;
}
elem dequeue()
{
elem tmp = root->data;
node* del = root;
root = merge(root->left, root->right);
delete del;
currentsize--;
return tmp;
}
static node* treemerge(priorityqueue& n1, priorityqueue& n2)
{
int size = n1.size() + n2.size();
n1.setsize(size);
n2.setsize(size);
return n1.merge(n1.getroot(), n2.getroot());
}
/*
priorityqueue operator= (priorityqueue &other)
{
if (&other == this) return *this;
deletedata(root);
currentsize = 0;
while (other.size())
enqueue(other.dequeue());
return *this;
}
*/
node* merge(node* n1, node* n2)//whether continue or direction? (minimum leftist heaps)
{
if (n1 == NULL)
return n2;
if (n2 == NULL)
return n1;
if (n1->data < n2->data)
{
mergeoperate(n1, n2);
return n1;//
}
else
{
mergeoperate(n2, n1);
return n2;//
}
}
node* mergeoperate(node* n1, node* n2)
{
if (n1->left == NULL)
{
n1->left = n2;
return n1;
}
else
{
n1->right = merge(n1->right, n2);
if (n1->left->npl < n1->right->npl)
{
swap(n1);
}
n1->npl = n1->right->npl + 1;
}
return n1;
}
};