Pagini recente » Cod sursa (job #726915) | Cod sursa (job #2578243) | Cod sursa (job #2032505) | Cod sursa (job #1070119) | Cod sursa (job #2756709)
#include<bits/stdc++.h>
#define god dimasi5eks
#pragma GCC optimize("O3")
#define fi first
#define se second
#define pb push_back
#define pf push_front
// #define fisier 1
using namespace std;
typedef long long ll;
const int mod = 1000000007;
const double dancila = 3.14159265359; // PI
const double eps = 1e-9;
int n, q;
struct nd
{
int cheie, grad;
nd *nxt, *frt, *tt;
nd()
{
cheie = grad = 0;
nxt = frt = tt = NULL;
}
};
nd* new_node(int val)
{
nd* temp = new nd;
temp -> cheie = val;
return temp;
}
struct binomial_heap
{
list <nd*> hp;
list <nd*> :: iterator get_root() // se afla cheia maxima a unui nod din lista
{
list <nd*> :: iterator it_max;
nd* vmax = new_node(-(1<<30));
for(list <nd*> :: iterator it = hp.begin(); it != hp.end(); ++it)
if((*it) -> cheie > vmax -> cheie)
{
vmax = *it;
it_max = it;
}
return it_max;
}
void merge_tree(nd* tr1, nd* tr2) // unirea e la fel ca la paduri de multimi disjuncte, se uneste arborele cu grad mai mic la cel cu grad mai mare
{
if(tr1 -> cheie < tr2 -> cheie)
swap (*tr1, *tr2);
tr2 -> frt = tr1 -> nxt;
tr2 -> tt = tr1;
tr1 -> nxt = tr2;
tr1 -> grad++;
}
void delete_root(nd* tr, binomial_heap& heap) // stergerea radacinii se face ca la orice heap, impingand nodul in jos si schimbandu-se pozitiile nodurilor pe parcurs
{
if(tr -> grad == 0)
{
delete tr;
return;
}
nd* tr2 = tr;
tr -> nxt -> tt = NULL;
heap.hp.push_front(tr -> nxt);
tr = tr -> nxt;
while(tr -> frt)
{
tr -> frt -> tt = NULL;
heap.hp.push_front(tr -> frt);
tr = tr -> frt;
}
delete tr2;
}
void adjust()
{
if(hp.size() <= 1)
return;
list <nd*> :: iterator prev, curr, next, temp;
prev = curr = hp.begin();
curr++;
next = curr;
next++;
while(curr != hp.end())
{
while(( next == hp.end() || (*next) -> grad > (*curr) -> grad) && curr != hp.end() && (*prev) -> grad == (*curr) -> grad)
{
merge_tree(*curr, *prev);
temp = prev;
if(prev == hp.begin())
{
prev++;
curr++;
if(next != hp.end())
next++;
}
else
prev--;
hp.erase(temp);
}
prev++;
if(curr != hp.end())
curr++;
if(next != hp.end())
next++;
}
}
void push(int val) // la fiecare adaugare heapul trebuie ajustat
{
nd *tr = new_node(val);
hp.push_front(tr);
adjust();
}
int top() // cheia radacinii calculate mai sus
{
return (*get_root()) -> cheie;
}
// functioneaza similar cu merge sort-ul, interclasarea facandu-se in ordinea crescatoare a gradelor
void heap_union( binomial_heap& heap2)
{
list <nd*> :: iterator it1 = hp.begin(), it2 = heap2.hp.begin();
list <nd*> nw;
while(it1 != hp.end() && it2 != heap2.hp.end())
{
if((*it1) -> grad <= (*it2) -> grad)
{
nw.pb(*it1);
it1++;
}
else
{
nw.pb(*it2);
it2++;
}
}
while(it1 != hp.end())
{
nw.pb(*it1);
it1++;
}
while(it2 != heap2.hp.end())
{
nw.pb(*it2);
it2++;
}
heap2.hp.clear();
hp = nw;
adjust();
}
void pop() // radacina trebuie stearsa si heapul trebuie refacut
{
list<nd*> :: iterator root = get_root();
binomial_heap nw;
delete_root((*root), nw);
hp.erase(root);
heap_union(nw);
}
};
binomial_heap arb[102];
int main()
{
#ifdef fisier
ifstream cin("mergeheap.in");
ofstream cout("mergeheap.out");
#endif
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin >> n >> q;
for(int i = 1; i <= q; ++i)
{
int tip;
cin >> tip;
if(tip == 1)
{
int mult, val;
cin >> mult >> val;
arb[mult].push(val);
}
if(tip == 2)
{
int mult;
cin >> mult;
cout << arb[mult].top() << '\n';
arb[mult].pop();
}
if(tip == 3)
{
int a, b;
cin >> a >> b;
arb[a].heap_union(arb[b]);
}
}
return 0;
}