Cod sursa(job #3130648)

Utilizator infomatic2Liviu Firca infomatic2 Data 18 mai 2023 12:25:52
Problema Heapuri Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 18.91 kb
#include<vector>
#include<fstream>

using namespace std;

ofstream cout("heapuri.out");
ifstream cin("heapuri.in");
struct node{
    vector<int> separators{};
    vector<node*> children{};
    node* father;
    bool leaf;
    
    

};
template<size_t n>
struct btree{
    node* swapper;//swapper e bun ca sa vezi unde este succesorul unei valori
    node* seed;
    btree():seed(nullptr){static_assert(n>1);}
    node* findnode(int &value,node* x){/// apeleaza initial cu b.seed
        
        if(x){// daca b nu este vid sau am ajuns intrun nod care exista
            int size=x->separators.size();
            for(int i=0;i<size;++i){
                if(value<=x->separators[i]){
                    if(value==x->separators[i]){
                        value=i;
                        return x;
                    }
                    else if(not x->leaf){
                        return findnode(value,x->children[i]);
                    }
                    
                }
            }
            if(not x->leaf){
                return findnode(value,x->children[size]);
            }
            
        }
        return nullptr;
    }
    void insert(int value,node* x){// sa se apeleze cu initial cu b.seed
        if(x!=nullptr){  // daca b nu este gol  
            vector<int>&v=x->separators;
            int size=v.size();
            if(x->leaf){
            
                
                for(int i=0;i<size;++i){
                    if(value<=v[i]){
                        if(value!=v[i]){
                            v.insert(v.begin()+i,value);
                        }
                        break;
                    }
                    
                }
                if(value>v.back()){
                    v.push_back(value);
                }
            
                if(v.size()==2*n-1){
                    split(x);
                }
            }
            else{
                for(int i=0;i<size;i++){
                    if(value<v[i]){
                        insert(value,x->children[i]);
                        return;
                    }
                }
                if(value>v[size-1]){// foarte important sa nu facem nimic daca value se gaseste in multime
                    insert(value,x->children[size]);
                }
                
            }
        }
        else{
            node * s=new node();
            s->leaf=true;
            s->father=nullptr;
            s->separators.push_back(value);
            seed=s;
        }

    }

    void split(node*x){//nodul x are cu 1 prea multe valori
        if(x->father){//daca nu este in varf
            node*n1=new node();
            n1->father=x->father;
            n1->leaf=x->leaf;
            node * n2=new node();
            n2->father=x->father;
            n2->leaf=x->leaf;
            int half=x->separators.size()/2;
            int size=x->separators.size();
            
            if(not x->leaf){ // daca are copii ii copiez si pe aia
                for(int i=0;i<half;++i){
                    n1->separators.push_back(x->separators[i]);
                    n1->children.push_back(x->children[i]);
                    x->children[i]->father=n1;
                }
                n1->children.push_back(x->children[half]);
                x->children[half]->father=n1;
                for(int i=half+1;i<size;++i){
                    n2->separators.push_back(x->separators[i]);
                    n2->children.push_back(x->children[i]);
                    x->children[i]->father=n2;
                }
                n2->children.push_back(x->children[size]);
                x->children[size]->father=n2;
            }
            else{
                for(int i=0;i<half;++i){
                    n1->separators.push_back(x->separators[i]);
                    
                }
                for(int i=half+1;i<size;++i){
                    n2->separators.push_back(x->separators[i]);
                }
            }
            //acuma trebuie sa inserez cele doua noduri pe noul lor separator in tata
            node * tatal=x->father;
            
            int size2=tatal->separators.size();
            vector<int>&v=tatal->separators;
            for(int i=0;i<size2;i++){
                if(v[i]>x->separators[half]){
                    v.insert(v.begin()+i,x->separators[half]);
                    tatal->children[i]=n2;
                    tatal->children.insert(tatal->children.begin()+i,n1);
                    break;
                }

            }
            if(x->separators[half]>v.back()){
                
                tatal->children[v.size()]=n1;
                tatal->children.push_back(n2);
                v.push_back(x->separators[half]);
            }
            delete x;
            if(tatal->children.size()==2*n){
                split(tatal);
            }            
            return;

        }
        else{// este in varf: daca sunt prea multe valori trebuie sa construiesc un nou tata
            node * n2=new node();
            n2->leaf=x->leaf;

            node * n1=new node();
            n1->leaf=x->leaf;
            int half=x->separators.size()/2;
            int size=x->separators.size();
            if(not x->leaf){
                for(int i=0;i<half;++i){
                    n1->separators.push_back(x->separators[i]);
                    n1->children.push_back(x->children[i]);
                    x->children[i]->father=n1;
                }
                n1->children.push_back(x->children[half]);
                x->children[half]->father=n1;
                for(int i=half+1;i<size;++i){
                    n2->separators.push_back(x->separators[i]);
                    n2->children.push_back(x->children[i]);
                    x->children[i]->father=n2;
                }
                n2->children.push_back(x->children[size]);
                x->children[size]->father=n2;
            }
            else{
                for(int i=0;i<half;++i){
                    n1->separators.push_back(x->separators[i]);
                }
                for(int i=half+1;i<size;++i){
                    n2->separators.push_back(x->separators[i]);
                }
            }
            node* tatal=new node();// creez un nou varf in care se afla un singur element
            tatal->children.push_back(n1);
            tatal->children.push_back(n2);
            tatal->separators.push_back(x->separators[half]);
            seed=tatal;
            seed->leaf=false;
            n1->father=seed;
            n2->father=seed;
            tatal->father=nullptr;
            delete x;
        }
    }
    void lipseste1(node * x){// lipseste 1 este inversul lui split; x trebuie sa aiba tata
        node*y=x->father;
        
        int index;
        for(int i=0;i<y->children.size();++i){// trebuie sa il gasesc in tata
            if(x==y->children[i]){
                index=i;
                break;
            }
        }
        
        if(index==y->separators.size()){
            node * st=y->children[index-1];// fratele de la stanga
            if(st->separators.size()>n-1){// daca fratele are destule elemente sa ii dea
                if(st->leaf){
                    x->separators.insert(x->separators.begin(),y->separators[index-1]);
                    y->separators[index-1]=st->separators.back();
                    st->separators.pop_back();
                }
                else{
                    x->separators.insert(x->separators.begin(),y->separators[index-1]);
                    y->separators[index-1]=st->separators.back();
                    st->separators.pop_back();
                    x->children.insert(x->children.begin(),st->children.back());
                    st->children.back()->father=x; /// ii zic copilului ca are un nou tata
                    st->children.pop_back();
                }
            }
            else{
                
                
                node * nn=new node();
                nn->leaf=x->leaf;
                nn->father=x->father;
                if(not nn->leaf){
                    for(int i=0;i<st->children.size();i++){
                        nn->children.push_back(st->children[i]);
                        st->children[i]->father=nn;
                    }
                    for(int i=0;i<x->children.size();i++){
                        nn->children.push_back(x->children[i]);
                        x->children[i]->father=nn; 
                    }
                }
                nn->separators=st->separators;
                nn->separators.push_back(y->separators[index-1]);
                nn->separators.insert(nn->separators.end(),x->separators.begin(),x->separators.end());
                y->separators.pop_back();
                y->children.pop_back();
                y->children.pop_back();
                y->children.push_back(nn);
                delete x;
                delete st;
                if(y->father){// daca tatal lui x nu este in varf
                    if(y->separators.size()<n-1){
                        lipseste1(y);
                    }
                }
                else if(y->separators.size()==0){
                    seed=nn;
                    seed->father=nullptr;
                    delete y;
                }
            }

        }
        else if(index !=0){
            node * st=y->children[index-1];// fratele de la stanga
            node * dr=y->children[index+1]; // fratele de la dreapta
            if(st->separators.size()>n-1){// daca fratele  stang are destule elemente sa ii dea
                if(st->leaf){
                    x->separators.insert(x->separators.begin(),y->separators[index-1]);
                    y->separators[index-1]=st->separators.back();
                    st->separators.pop_back();
                }
                else{
                    x->separators.insert(x->separators.begin(),y->separators[index-1]);
                    y->separators[index-1]=st->separators.back();
                    st->separators.pop_back();
                    x->children.insert(x->children.begin(),st->children.back());
                    st->children.back()->father=x;
                    st->children.pop_back();
                }
            }

            else if(dr->separators.size()>n-1){
                if(x->leaf){
                    x->separators.push_back(y->separators[index]);
                    y->separators[index]=dr->separators[0];
                    dr->separators.erase(dr->separators.begin());
                }
                else{
                    x->separators.push_back(y->separators[index]);
                    y->separators[index]=dr->separators[0];
                    dr->separators.erase(dr->separators.begin());
                    x->children.push_back(dr->children[0]);
                    dr->children[0]->father=x;
                    dr->children.erase(dr->children.begin());
                }
            }
            else{
                node * nn=new node();
                nn->leaf=x->leaf;
                nn->father=x->father;
                for(int i=0;i<st->children.size();i++){
                    nn->children.push_back(st->children[i]);
                    st->children[i]->father=nn;
                }

                for(int i=0;i<x->children.size();i++){
                    nn->children.push_back(x->children[i]);
                    x->children[i]->father=nn;
                }
                
                nn->separators=st->separators;
                nn->separators.push_back(y->separators[index-1]);
                nn->separators.insert(nn->separators.end(),x->separators.begin(),x->separators.end());
                
                y->separators.erase(y->separators.begin()+index-1);    
                y->children.erase(y->children.begin()+index);
                y->children[index-1]=nn;
                
                delete x;
                delete st;
                if(y->father){// daca tatal lui x nu este in varf
                    if(y->separators.size()<n-1){
                        lipseste1(y);
                    }
                }
                else if(y->separators.size()==0){
                    seed=nn;
                    seed->father=nullptr;
                    delete y;
                }
            }
        }
        else{
            node * dr=y->children[index+1];
            if(dr->separators.size()>n-1){
                if(x->leaf){
                    x->separators.push_back(y->separators[index]);
                    y->separators[index]=dr->separators[0];
                    dr->separators.erase(dr->separators.begin());
                }
                else{
                    x->separators.push_back(y->separators[index]);
                    y->separators[index]=dr->separators[0];
                    dr->separators.erase(dr->separators.begin());
                    x->children.push_back(dr->children[0]);
                    dr->children[0]->father=x;
                    dr->children.erase(dr->children.begin());
                }
            }
            else{
                node * nn=new node();
                nn->leaf=x->leaf;
                nn->father=x->father;
                for(int i=0;i<x->children.size();i++){
                    nn->children.push_back(x->children[i]);
                    x->children[i]->father=nn;
                }
                for(int i=0;i<dr->children.size();i++){
                    nn->children.push_back(dr->children[i]);
                    dr->children[i]->father=nn;
                }
                
                nn->separators=x->separators;
                nn->separators.push_back(y->separators[0]);
                nn->separators.insert(nn->separators.end(),dr->separators.begin(),dr->separators.end());
                
                y->separators.erase(y->separators.begin());
                y->children.erase(y->children.begin());
                y->children[0]=nn;
                delete x;
                delete dr;
                if(y->father){// daca tatal lui x nu este in varf
                    if(y->separators.size()<n-1){
                        lipseste1(y);
                    }
                }
                else if(y->separators.size()==0){
                    seed=nn;
                    seed->father=nullptr;
                    delete y;
                }
            }
        }

        
    }
    int succesor(int value,node* x,int index){// sa se afle succesorul valorii value care se afla pe pozitia index in nodul x si x nu este frunza
        node *y=x->children[index+1];
        while (not y->leaf){
        y=y->children[0];
            
        }
        swapper=y;
        return y->separators[0];
    }
    void sterge(int value){
        int index=value;
        node * y=findnode(index,seed);
        if(y){    
            if(y->leaf){
                if(y->father){    
                    y->separators.erase(y->separators.begin()+index);
                    if(y->separators.size()<n-1){
                        lipseste1(y);
                    }
                }
                else if(y->separators.size()>1){
                    y->separators.erase(y->separators.begin()+index);
                }
                else if(y->separators.size()==1){// exista un singur nod in arbore
                    delete y;
                    seed=nullptr;
                    
                }
            }
            else{
                int temp=succesor(value,y,index);
                y->separators[index]=temp;
                swapper->separators.erase(swapper->separators.begin());
                if(swapper->separators.size()<n-1){
                    lipseste1(swapper);
                }

            }
        }
    }
    node* cmmn(int& value,node*x){// sa se apeleze initial cu b.seed pentru intrebarea 4
        if(not x->leaf){
            int size=x->separators.size();
            for(int i=0;i<size;++i){
                if(value<=x->separators[i]){
                    if(value==x->separators[i]){
                        value=i;
                        return x;
                    }
                    int temp=value;
                    
                    node* test= cmmn(value,x->children[i]);
                    if(test->separators[value]<=temp){
                        return test;
                    }
                    else if(i!=0){
                        value=i-1;
                        return x;
                    }
                    else{
                        value=0;// trebuie sa returneze ceva daca nu s-a dus unde trebuie
                        return x;
                    }
                
                }
            }
            int temp=value;
                    
            node* test= cmmn(value,x->children[size]);
            if(test->separators[value]<=temp){
                return test;
            }
            else{
                value=size-1;
                return x;
            }
        }
        else{
            int i=0,size=x->separators.size();

            while(i+1<size&&x->separators[i+1]<=value){
                i++;
            }
            value=i;
            return x;
        }
    }
    int cmmn4(int x){
        int value=x;
        node* y=cmmn(value,seed);
        return y->separators[value];
    }

    node* Cmmn5(int& value,node *x){// sa se apeleze initial cu seedul
        if(not x->leaf){
            int size=x->separators.size();
            for(int i=0;i<size;++i){
                if(value<=x->separators[i]){
                    if(value==x->separators[i]){
                        value=i;
                        return x;
                    }
                    int temp=value;

                    node * test=Cmmn5(value,x->children[i]);
                    if(test->separators[value]>=temp){
                        return test;
                    }
                    else{
                        value=i;
                        return x;
                    }

                }
            }
            return Cmmn5(value,x->children.back());
        }
        else{
            int i=0,size=x->separators.size();
            while(i+1<size&&x->separators[i]<value){ // este un bug!!!!!!!!!!!!!!!!!!!!!1
                i++;
            }
            value=i;
            return x;

        }
    }

    int cmmn5(int value){
        int temp=value;
        node* y=Cmmn5(temp,seed);
        return y->separators[temp];
    }
    int minimum(node* s){
        if(s->leaf){
            return s->separators[0];
        }
        else{
            return minimum(s->children[0]);
        }
    }
    
    size_t size(){
        return n;
    }

};




int main(){
    btree<20> b;
    vector<int> v;
    int x,y,n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>x;
        switch(x){
            case 1:
                {
                    cin>>y;
                    v.push_back(y);
                    b.insert(y,b.seed);
                }
                break;

            case 2:
                {
                    cin>>y;
                    b.sterge(v[y-1]);
                }
                break;
            case 3:
                {
                    cout<<b.minimum(b.seed)<<'\n';
                }
        }
    }

}