Cod sursa(job #2656568)

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

using namespace std;

fstream 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() % 100000;
        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 prioritate);
    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;
        }
    }
    update(nod);
    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 RandomInput(){
    /// generez operatii random si vad ca am un timp de executie < 0.5s
    /// totusi de ce TLE??? hmmmm
    int limit = 300000;
    for(int i = 1; i <= limit; i++){
        int nr = rand() % int(1e9);
        int op = rand() % 5 + 1; /// am 5 operatii
        char chr;
        if(op == 1)
            chr = 'I';
        else if(op == 2)
            chr = 'S';
        else if(op == 3)
            chr = 'C';
        else if(op == 4)
            in<<"MIN";
        else
            in<<"MAX";
        if(op <= 3)
            in<<chr<<" "<<nr;
        in<<"\n";
    }
}

int main()
{
    srand(time(0));

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

    ///RandomInput();
    Zeap zeap; /// asta nu il fac pointer prea multi pointeri god damn
    char prima;
    int nr;

    while((prima = in.get()) && prima != EOF){
        if(prima != 'M')
            in>>nr;
        if(prima == 'I'){
            if(zeap.find(nr) == NIL)
                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(prima == 'M'){
            in.get(prima);
            if(prima == 'I'){
                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';
            }
            in.get(); /// citesc si ultimul I
        }
        in.get();
    }

    return 0;
}