Cod sursa(job #2620893)

Utilizator vladdudauDudau Vlad vladdudau Data 29 mai 2020 20:24:55
Problema Heapuri Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 7.09 kb
#include <bits/stdc++.h>
using namespace std;
ifstream fin("heap.in");
ofstream fout("heap.out");
///Nodul unui Treap
struct Treap
{
    int cheie, prioritate;
    Treap *vec_stanga, *vec_dreapta;
};

Treap *RotireLaDreapta(Treap *y)
{
    Treap *x = y->vec_stanga,  *T2 = x->vec_dreapta;

    /// Realizeaza rotatia
    x->vec_dreapta = y;
    y->vec_stanga = T2;

    /// Returneaza noul treap
    return x;
}

Treap *RotireLaStanga(Treap *x)
{
    Treap *y = x->vec_dreapta, *T2 = y->vec_stanga;

    ///Realizaeza rotatia
    y->vec_stanga = x;
    x->vec_dreapta = T2;

    ///Returneaza noul treap
    return y;
}

/// Ma ajuta sa adaug o noua cheie
Treap* NewNod(int cheie)
{
    Treap* temporar = new Treap;
    temporar->cheie = cheie;
    temporar->prioritate = rand()%100;
    temporar->vec_stanga = temporar->vec_dreapta = NULL;
    return temporar;
}

///valoarae minima din Treap
int ValoareMinima(Treap* treap)
{
    if(treap==NULL)
        return INT_MAX;
    Treap* copie=treap;

///Cauta frunza cea mai din stanga
while (copie->vec_stanga != NULL)
{
    copie = copie->vec_stanga;
}
return(copie->cheie);
}

///functie care cauta valoarea maxima din Treap
int ValoareMaxima(Treap* treap)
{
    ///Caz de baza
    if (treap == NULL)
    return INT_MIN;

    /// Returneaza maximul a 3 valori
    /// 1) Cheia Radacinii 2) Maximul din subarborele din stanga
    /// 3) Maximul din subarborele din dreapta
    int Max1 = treap->cheie;
    int Max2 = ValoareMaxima(treap->vec_stanga);
    int Max3 = ValoareMaxima(treap->vec_dreapta);
    if (Max2 > Max1)
    Max1 = Max2;
    if (Max3 > Max1)
    Max1 = Max3;
    return Max1;
}

///Gaseste predecesorul unei chei
void GasestePredecesor(Treap* treap, Treap*& predecesor, int cheie)
{
    ///Cazul de baza
    if (treap == NULL ||ValoareMinima(treap)>=cheie)  return ;

    ///Daca cheia e in radacina
    if (treap->cheie == cheie)
    {
        ///Valoarea maxima din subarborele din stanga este predecesor
        if (treap->vec_stanga != NULL)
        {
            Treap* temporar = treap->vec_stanga;
            while (temporar->vec_dreapta)
                temporar = temporar->vec_dreapta;
            predecesor = temporar ;
        }
        return;
    }

    ///Daca cheia din radacina e mai mare decat cheia introdusa, cautam in subarborele din dreapta
    if (treap->cheie > cheie)
    {
        GasestePredecesor(treap->vec_stanga,predecesor, cheie) ;
    }
    else
    {
        predecesor=treap;
        GasestePredecesor(treap->vec_dreapta,predecesor, cheie) ;
    }
}

///Gaseste succesorul unei chei
void GasesteSuccesor(Treap* treap, Treap*& succesor, int cheie)
{
    ///Caz de baza
    if (treap == NULL ||ValoareMaxima(treap)<=cheie)  return ;

    ///Daca cheia se afla in radacina
    if (treap->cheie == cheie)
    {

        if (treap->vec_dreapta != NULL)
        {
            Treap* temporar = treap->vec_dreapta ;
            while (temporar->vec_stanga)
                temporar = temporar->vec_stanga ;
            succesor = temporar ;
        }
        return ;
    }

    if (treap->cheie > cheie)
    {
        succesor = treap ;
        GasesteSuccesor(treap->vec_stanga,succesor, cheie) ;
    }
    else
    {
        GasesteSuccesor(treap->vec_dreapta,succesor, cheie) ;
    }
}

///cauta o cheie in Treap
Treap* Cauta(Treap* treap, int cheie)
{
    /// Cazul de baza, treapul e null sau cheia e in radacina
    if (treap == NULL || treap->cheie == cheie)
       return treap;

    /// Cheia este mai mare decat cheia radacinii
    if (treap->cheie < cheie)
       return Cauta(treap->vec_dreapta, cheie);

    /// Cheia este mai mica decat cheia radacinii
    return Cauta(treap->vec_stanga, cheie);
}

///Inserare in Treap
Treap* Insereaza(Treap* treap, int cheie)
{
    /// Daca treapul e null creez un nou nod si l returnez
    if (!treap)
        return NewNod(cheie);

    /// Daca cheia este mai mica decat cheia radacinii
    if (cheie <= treap->cheie)
    {
        /// Inserez in subarborele din stanga
        treap->vec_stanga = Insereaza(treap->vec_stanga, cheie);

        if (treap->vec_stanga->prioritate > treap->prioritate)
            treap = RotireLaDreapta(treap);
    }
    else  /// Daca cheia este mai mare
    {
        /// Inserez in subarborele din dreapta
        treap->vec_dreapta = Insereaza(treap->vec_dreapta, cheie);

        if (treap->vec_dreapta->prioritate > treap->prioritate)
            treap = RotireLaStanga(treap);
    }
    return treap;
}

///Stergerea unui element din Treap
Treap* StergeNod(Treap* treap, int cheie)
{
    if (treap == nullptr)
        return treap;

    if (cheie < treap->cheie)
        treap->vec_stanga = StergeNod(treap->vec_stanga, cheie);
    else if (cheie > treap->cheie)
        treap->vec_dreapta = StergeNod(treap->vec_dreapta, cheie);

    else if (treap->vec_stanga == NULL)
    {
        Treap *temporar = treap->vec_dreapta;
        delete(treap);
        treap = temporar;  /// Fac copilul din dreapta sa fie radacina
    }


    else if (treap->vec_dreapta == NULL)
    {
        Treap *temp = treap->vec_stanga;
        delete(treap);
        treap = temp;  ///fac copilul din stanga sa fie radacina
    }

    /// Daca cheia este in radacina si left si right nu sunt nule
    else if (treap->vec_stanga->prioritate < treap->vec_dreapta->prioritate)
    {
        treap = RotireLaStanga(treap);
        treap->vec_stanga = StergeNod(treap->vec_stanga, cheie);
    }
    else
    {
        treap = RotireLaDreapta(treap);
        treap->vec_dreapta = StergeNod(treap->vec_dreapta, cheie);
    }

    return treap;
}

///Afiseaza arborele impreuna cu copiii sai
void AfisareInOrdine(Treap* treap)
{
    if (treap)
    {
        AfisareInOrdine(treap->vec_stanga);
        cout << "cheie: "<< treap->cheie << " | prioritate: "
            << treap->prioritate;
        if (treap->vec_stanga)
            cout << " | copilul din stanga: " << treap->vec_stanga->cheie;
        if (treap->vec_dreapta)
            cout << " | copilul din dreapta: " << treap->vec_dreapta->cheie;
        cout << endl;
        AfisareInOrdine(treap->vec_dreapta);
    }
}

void AfisareInOrdineCrescatoare(Treap* treap)
{
     if (treap == NULL)
        return;
    if (treap != NULL)
    {
        AfisareInOrdineCrescatoare(treap->vec_stanga);
        cout<<treap->cheie<<"  ";
        AfisareInOrdineCrescatoare(treap->vec_dreapta);
    }
}
int ordine[200001],n,ord=0;
int main()
{
    srand(time(NULL));
    struct Treap *treap = NULL;
    fin>>n;
    for(int i=1;i<=n;i++)
    {
        int alegere;
        fin>>alegere;
        if(alegere==1)
        {
            int x;
            fin>>x;
            treap=Insereaza(treap,x);
            ordine[++ord]=x;
        }
        else if(alegere==2)
        {
            int x;
            fin>>x;
            treap=StergeNod(treap,ordine[x]);
        }
        else
        {
            fout<<ValoareMinima(treap)<<"\n";
        }
    }
    return 0;
}