Cod sursa(job #2756709)

Utilizator stefdascalescuStefan Dascalescu stefdascalescu Data 2 iunie 2021 16:28:04
Problema Heapuri cu reuniune Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.82 kb
#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;
}