Pagini recente » Infoarena Monthly 2014 - Solutii Runda 3 | Cod sursa (job #2687355) | Cod sursa (job #448614) | Cod sursa (job #487749) | Cod sursa (job #3130648)
#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';
}
}
}
}