Cod sursa(job #2656553)

Utilizator nicolaefilatNicolae Filat nicolaefilat Data 7 octombrie 2020 23:04:52
Problema Zeap Scor 10
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 6.73 kb
#include <iostream>
#include <fstream>
#include <time.h>
#include <cstdlib>

using namespace std;

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

int maxim(int a,int b){
    if(a > b)
        return a;
    return b;
}
int minim(int a,int b){
    if(a < b)
        return a;
    return b;
}
int min(int a,int b,int c = 2e9){
    return minim(a,minim(b,c));
}
int max(int a,int b,int c = 0){
    return maxim(a,maxim(b,c));
}


struct Nod{
    int val;
    int prioritate;
    Nod *st,*dr;
    int minim,maxim;
    int diferentaMinima;

    Nod(){
        st = dr = nullptr;
        prioritate = rand() % 100;
        val = 0;
        minim = 2e9;
        maxim = -2e9;
        diferentaMinima = 2e9;
    }
    Nod(int valoare,Nod *nul){
        st = dr = nul;
        prioritate = rand() % 100;
        val = minim = maxim = valoare;
        diferentaMinima = 2e9;
    }
};
Nod *NIL = new Nod();

/// treap cu prioritati de heap de maxim, radacina are cea mai mare prioritate
class Zeap{
public:
    int elemente = 0;
    Zeap(){
        radacina = NIL;
    }
    void insert(int val,int p = -1){
        insereaza(radacina,val,p);
    }
    void erase(int val){
        sterge(radacina,val);
    }
    Nod *find(int val){
        return gaseste(radacina,val);
    }
    void print(){
        cout<<"Val maxim "<<radacina->maxim<<"\n";
        cout<<"Val minim "<<radacina->minim<<"\n";
        cout<<"Dif Min "<<radacina->diferentaMinima<<"\n";
        afisare(radacina);
        cout<<"\n";
    }
    void debug(bool detailed = true){
        cout<<"Val maxim "<<radacina->maxim<<"\n";
        cout<<"Val minim "<<radacina->minim<<"\n";
        cout<<"Dif Min "<<radacina->diferentaMinima<<"\n";
        inordine(radacina,detailed);
        cout<<"\n";
    }
    Nod * radacina = NIL;
private:
    void leftRotate(Nod *& tata);
    void rightRotate(Nod *& tata);

    void update(Nod *& nod);

    void insereaza(Nod *& radacina, int val,int );
    void sterge(Nod *& radacina, int val);
    Nod* gaseste(Nod * radacina,int val);


    void afisare(Nod *radacina);
    void inordine(Nod *radacina,bool);
};

void Zeap::update(Nod *& nod){
    nod->maxim = max(nod->val,nod->st->maxim,nod->dr->maxim);
    nod->minim = min(nod->val,nod->st->minim,nod->dr->minim);
    nod->diferentaMinima = min(nod->val - nod->st->maxim,nod->dr->minim - nod->val);
    nod->diferentaMinima = min(nod->diferentaMinima,nod->dr->diferentaMinima,nod->st->diferentaMinima);
    if(nod->diferentaMinima < 0){
        cout<<"NOOOOOOOOOOOOO"<<"\n";
        cout<<nod->val<<" "<<nod->st->maxim<<" "<<nod->dr->minim<<endl;
        cout<<"DEBUG"<<endl;
        debug();
    }
    //nod->diferentaMinima = min(nod->diferentaMinima,nod->st->diferentaMinima,nod->dr->diferentaMinima);
}
void Zeap::insereaza(Nod *& nod,int val,int prioritate = -1){
    if(nod == NIL){
        elemente++;
        nod = new Nod(val,NIL);
        if(prioritate != -1)
            nod->prioritate = prioritate;
        return;
    }
    if(nod->val < val){
        insereaza(nod->dr,val,prioritate);
        /// am inserat in dreapta
        if(nod->dr->prioritate > nod->prioritate){
            leftRotate(nod);
            update(nod->st);
        }
    }else if(nod->val > val){
        insereaza(nod->st,val,prioritate);
        if(nod->st->prioritate > nod->prioritate){
            rightRotate(nod);
            update(nod->dr);
        }
    }
    update(nod);
}
void Zeap::sterge(Nod *& nod,int val){
    if(nod == NIL){
        return;
    }
    if(nod->val == val){
        if(nod->st != NIL && nod->dr != NIL){
            if(nod->st->prioritate > nod->dr->prioritate)
                rightRotate(nod);
            else
                leftRotate(nod);
        }else if(nod->st != NIL)
            rightRotate(nod);
        else if(nod->dr != NIL)
            leftRotate(nod);
        else{
            elemente--;
            nod = NIL;
            return;
        }
    }
    if(nod->val > val)
        sterge(nod->st,val);
    else
        sterge(nod->dr,val);
    update(nod);
}
Nod *Zeap::gaseste(Nod * nod, int val){
    if(nod == NIL)
        return nod;
    if(nod->val > val)
        return gaseste(nod->st,val);
    else if(nod->val < val)
        return gaseste(nod->dr,val);
    else
        return nod;
}
void Zeap::leftRotate(Nod *& tata){
    Nod *fiu = tata->dr; /// il iau pe fiu si il rotesc in stanga
    tata->dr = fiu->st;
    fiu->st = tata;
    tata = fiu; /// sa am pointer-ul intr-o pozitie buna
}
void Zeap::rightRotate(Nod *& tata){
    Nod *fiu = tata->st; /// il iau pe fiul stanga si il rotesc in dreapta
    tata->st = fiu->dr;
    fiu->dr = tata;
    tata = fiu;
}
void Zeap::inordine(Nod *r,bool detailed){
    if(r == NIL)
        return;
    if(detailed){
        cout<<"Nodul : "<<r->val<<" cu prioritate : "<<r->prioritate<<" | ";
        cout<<"Maxim : "<<r->maxim<<" "<<"Minim : "<<r->minim<<" "<<"Dif Min "<<r->diferentaMinima<<"\n";
    }
    else
        cout<<r->val<<" ";
    inordine(r->st,detailed);
    inordine(r->dr,detailed);
}
void Zeap::afisare(Nod *r){
    if(r == NIL)
        return;
    afisare(r->st);
    cout<<r->val<<" ";
    afisare(r->dr);
}
void test(){
    Zeap zeap;
    for(int i = 1; i <= 10; i++){
        zeap.insert(rand() % 10);
    }
    zeap.print();
    zeap.debug();
    for(int i = 1; i <= 10; i++){
        int val = rand() % 10;
        cout<<"Sterg "<<val<<endl;
        zeap.erase(val);
        zeap.print();
        zeap.debug();
    }
}

int main()
{
    in.tie(0);
    out.tie(0);
    ios::sync_with_stdio(false);

    Zeap zeap;
    string s;
    int nr;
    while(getline(in,s)){
        char prima = s[0];
        if(prima != 'M'){
            nr = 0;
            for(int i = 2; i < s.size(); i++)
                nr = nr * 10 + s[i] - '0';
        }
        if(prima == 'I'){
            if(zeap.find(nr) != NIL)
                out<<-1<<"\n";
            else
                zeap.insert(nr);
        }else if(prima == 'S'){
            if(zeap.find(nr) == NIL)
                out<<-1<<"\n";
            else
                zeap.erase(nr);
        }else if(prima == 'C'){
            if(zeap.find(nr) != NIL)
                out<<1;
            else
                out<<0;
            out<<"\n";
        }else if(s == "MIN"){
            if(zeap.elemente < 2)
                out<<-1<<"\n";
            else
                out<<zeap.radacina->diferentaMinima<<"\n";
        }else{
            if(zeap.elemente < 2)
                out<<-1<<"\n";
            else
                out<<zeap.radacina->maxim - zeap.radacina->minim<<"\n";
        }
    }

    return 0;
}