Cod sursa(job #2749995)

Utilizator ionut31Ioan Ionescu ionut31 Data 9 mai 2021 11:41:54
Problema Zeap Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.99 kb
#include <fstream>
#include <iostream>
#include <set>
#include <queue>
#include <string>

using namespace std;

ifstream fin ("zeap.in");
ofstream fout ("zeap.out");


struct pereche //strucutra ce retine doua elemente vecine din zeap
{
    int st,dr;
    pereche(){}
    pereche(int x, int y)
    {
        st = x;
        dr = y;
    }
};


class cmp //clasa de comparator pentru priority queue
{
public:
    bool operator () (const pereche& a, const pereche& b) //supraincarc operatorul () pentru a compara doua perechi
    {
        return abs(a.st - a.dr) > abs(b.st - b.dr); //compar diferentele dintre elementele perechilor
    }
};

priority_queue<pereche, vector<pereche>, cmp> PQ; //priority queue se va implementa printr-un vector de perechi,
                                                 // utilizand comparatorul cmp


//functia de inserare a unui element in zeap-ul Z
//care insereaz un element daca acesta nu exista deja in zeap si intoarce 1,
//iar in caz contrat intoarce -1
int insereaza(set<int> &Z,int x)
{
    if(!Z.count(x)) //testez daca Z nu il contine deja pe x
    {
        Z.insert(x); //daca nu il contine deja, il adaug
        return 1;
    }
    else return -1;

}

//functia de stergere a unui element din zeap-ul Z(functia va returna 1 daca stergerea a reusit si -1 in caz contrat,
// adica daca x nu se afla in Z)
int sterge(set<int> &Z,int x)
{
    if(!Z.count(x)) //testez daca Z nu il contine pe x
        return -1;
    else //daca sterg elementul, inainte de stergere aflu pozitia sa, il elimin si apoi fac pereceh intre
         //vecinul sau din stanga si vecinul sau din dreapta
    {
        //it1 = vecin din stanga, it2 = vecin din dreapta
        set<int>::iterator it1 = Z.find(x);
        set<int>::iterator it2 = it1;
        ++it2;
        if(it1 != Z.begin() && it2 != Z.end()) //verific daca am ambii vecini
        {
            --it1; //scad it1 dupa verificare, deoarece pozitia lui x poate fi chiar Z.begin()+1
            PQ.push(pereche(*it1, *it2));
        }
        Z.erase(x);
        return 1;
    }
}


//functie care cauta elementul x in zeap-ul Z si returneaza 0 daca elementul nu exista si 1 daca exista
int cauta(set<int> &Z,int x)
{
    if(Z.count(x))
        return 1;
    else
        return 0;
}

//functie care returneaza diferenta in modul maxima dintre oricare doua elemente distincte din zeap-ul Z;
//daca nu exista cel putin doua elemente in zeap se returneaza -1;
int max_dif(set<int> &Z)
{
    //set-ul este implementat cu un arbore binar de cautare, asta inseamna ca primul element este cel mai mic,
    //iar ultimul element este cel mai mare(set-ul este ordonat)

    if(Z.size() < 2) //am cel mult un element, deci nu pot avea diferenta dintre 2 numere distincte
        return -1;
    else
    {
        set<int>::iterator prim = Z.begin(), ultim = Z.end();
        --ultim; //deoarece Z.end() intoarce prima adresa din afara setului
        return *ultim - *prim;
    }
}

//functie care returneaza diferenta in modul minima dintre oricare doua elemente distincte din zeap-ul Z;
//daca nu exista cel putin doua elemente in zeap se returneaza -1;
int min_dif(set<int> &Z)
{
    if(Z.size() < 2) //am cel mult un element, deci nu pot avea diferenta dintre 2 numere distincte
        return -1;
    else
    {
        //cat timp perechea din varful cozii cu prioritati(perechea cu diferenta minima) este incompleta
        while(!Z.count(PQ.top().st) ||!Z.count(PQ.top().dr))
        {
            PQ.pop();
        }
        return abs(PQ.top().st - PQ.top().dr);
    }
}

int main()
{
    set<int> Z;

    string s;
    int x;
    while(fin >> s)
    {
        if(s == "I")
        {
            fin >> x;
            int rez = insereaza(Z, x);
            if(rez == 1) //daca am inserat elementul nou
            {
                set<int>::iterator it = Z.find(x); //aflu pozitia din zeap unde a fost inserat
                //apoi fac perechile dintre elementul curent si vecinii sai
                if(it != Z.begin())
                {
                    set<int>::iterator it2 = it; //vecinul din stanga
                    --it2;
                    PQ.push(pereche(*it2, x)); //pun perechea formata in PQ
                }

                set<int>::iterator it3 = it; //vecinul din dreapta
                ++it3;
                if(it3 != Z.end())
                {
                    PQ.push(pereche(x, *it3)); //pun perechea formata in PQ
                }
            }
        }
        else if(s == "S")
        {
            fin >> x;
            int rez = sterge(Z, x) ;
            if(rez == -1)
                fout << "-1\n";
        }
        else if(s == "C")
        {
            fin >> x;
            fout << cauta(Z, x) << "\n";
        }
        else if(s == "MIN")
        {
            fout << min_dif(Z) << "\n";
        }
        else
        {
            fout << max_dif(Z) << "\n";
        }
    }
    return 0;
}