Pagini recente » Cod sursa (job #174295) | Cod sursa (job #2726976) | Cod sursa (job #1646464) | Cod sursa (job #898166) | Cod sursa (job #1253427)
#include <fstream>
#include <cstring>
#include <iostream>
using namespace std;
ifstream fin("zeap.in");
ofstream fout ("zeap.out");
// AVL Tree Implementation - Mihai Nitu, 2014
int max (int a, int b)
{
return a > b ? a : b;
}
template <class TEMPLATE>
class AVL;
template <class TEMPLATE> // needs ==, < and > operators
class node
{
node <TEMPLATE> *left,*right;
int count, balance, subtree, maxdepth;
//RECALCULATIONS
void get_maxdepth ()
{
maxdepth = 0;
if (left != NULL)
maxdepth = max (maxdepth,left->maxdepth+1);
if (right != NULL)
maxdepth = max (maxdepth,right->maxdepth+1);
}
void get_subtree ()
{
subtree = count;
if (left != NULL)
subtree += left->subtree;
if (right != NULL)
subtree += right->subtree;
}
void get_balance ()
{
if (left != NULL && right != NULL)
balance = left->maxdepth - right->maxdepth;
else if (left != NULL)
balance = left->maxdepth+1;
else if (right != NULL)
balance = -right->maxdepth-1;
else balance = 0;
}
void recalculate ()
{
get_maxdepth();
get_subtree();
get_balance ();
}
public:
TEMPLATE data;
//Constructor
node <TEMPLATE> (TEMPLATE x, int cnt)
{
data = x;
count = cnt;
balance = 0;
maxdepth = 0;
subtree = 1;
left = NULL;
right = NULL;
}
friend class AVL<TEMPLATE>;
};
//Implementation philosophy:
//I've given each method a public and a private "version". The public versions are the ones called from the program to perform operations
//and they usually summon the private versions which are all recursive. Private versions return pointers to nodes in the tree so that they may be potentially
//used by other methods of the class to change the structure of the tree (except for erase and insert which return pointers to save the changes to
//updated nodes). Public versions only return the information (TEMPLATE) requested.
template <class TEMPLATE>
class AVL
{
node <TEMPLATE> *root/*root of the tree*/, *current /*pointer used to store temporary node*/;
TEMPLATE search_value /*used to store temporary search value*/, bad_signal /*value chosen upon declaration to signal that a given operation is invalid*/;
int nr_objects /*number of elements in tree*/, to_erase /*number of elements to erase used in erase function*/;
public:
//size function
int size ()
{
return nr_objects;
}
//CONSTRUCTOR
AVL (TEMPLATE bs = 0)
{
root = NULL;
nr_objects = 0;
bad_signal = bs;
}
//DESTRUCTOR
void destroy (node <TEMPLATE> *T)
{
if (T->left != NULL)
destroy (T->left);
if (T->right != NULL)
destroy (T->right);
delete T;
}
~AVL ()
{
if (root != NULL)
destroy (root);
}
//BALANCE
private:
node <TEMPLATE> *rotate_left (node <TEMPLATE> * T)
{
node <TEMPLATE> *save = T->right;
T->right = save->left;
save->left = T;
T->recalculate();
save->recalculate();
return save;
}
node <TEMPLATE> *rotate_right (node <TEMPLATE> * T)
{
node <TEMPLATE> *save = T->left;
T->left = save->right;
save->right = T;
T->recalculate();
save->recalculate();
return save;
}
node <TEMPLATE> *repair (node <TEMPLATE> *T)
{
T->recalculate();
if (T->balance == 2)
{
if (T->left->balance < 0)
{
T->left = rotate_left (T->left);
}
T = rotate_right (T);
}
else if (T->balance == -2)
{
if (T->right->balance > 0)
{
T->right = rotate_right (T->right);
}
T = rotate_left (T);
}
return T;
}
//INSERTION
private:
node<TEMPLATE> *insert (node <TEMPLATE> *T)
{
if (T == NULL)
return current;
else if (current->data == T->data)
{
T->count += current->count;
}
else if (current->data < T->data)
{
T->left = insert(T->left);
}
else
{
T->right = insert (T->right);
}
T = repair (T);
return T;
}
public:
void insert (TEMPLATE x) // inserts one object of value x
{
current = new node<TEMPLATE> (x,1);
root = insert(root);
++nr_objects;
}
void insert (TEMPLATE x, int nr) // inserts nr objects of value x
{
current = new node<TEMPLATE> (x,nr);
root = insert (root);
nr_objects += nr;
}
//SEARCH
private:
node <TEMPLATE> *find (node <TEMPLATE> *T)
{
if (T==NULL)
return NULL;
else if (search_value == T->data)
return T;
else if (search_value < T->data)
return find (T->left);
else return find (T->right);
}
public:
int find (TEMPLATE x) //returns number of appearances of x
{
search_value = x;
current = find (root);
if (current == NULL)
return 0;
return current->count;
}
//NEXT/PREV
private:
node<TEMPLATE> *next (node <TEMPLATE> *T)
{
if (T == NULL)
return NULL;
else if (T->data > search_value)
{
current = next (T->left);
if (current == NULL)
return T;
else return current;
}
else
{
return next (T->right);
}
}
node<TEMPLATE> *prev (node <TEMPLATE> *T)
{
if (T == NULL)
return NULL;
if (T->data < search_value)
{
current = prev (T->right);
if (current == NULL)
return T;
else return current;
}
else
{
return prev (T->left);
}
}
public:
TEMPLATE next (TEMPLATE x) //returns smallest object greater than x
{
search_value = x;
current = next (root);
if (current == NULL)
return bad_signal;
else return current->data;
}
TEMPLATE prev (TEMPLATE x) //returns greatest object smaller than x
{
search_value = x;
current = prev (root);
if (current == NULL)
return bad_signal;
else return current->data;
}
//MIN/MAX
private:
node <TEMPLATE> *min (node <TEMPLATE> *T)
{
if (T->left == NULL)
return T;
return min(T->left);
}
node <TEMPLATE> *max (node <TEMPLATE> *T)
{
if (T->right == NULL)
return T;
return max(T->right);
}
public:
TEMPLATE min () //returns minimum object
{
if (nr_objects == 0)
return bad_signal;
current = min (root);
return current->data;
}
TEMPLATE max () //returns maximum object
{
if (nr_objects == 0)
return bad_signal;
current = max (root);
return current->data;
}
//DELETION
private:
node <TEMPLATE> *erase (node <TEMPLATE> *T)
{
if (T == NULL)
return T;
else if (search_value == T->data)
{
if (T->count)
{
T->count -= to_erase;
nr_objects -= to_erase;
}
if (T->count == 0)
{
if (T->left == NULL && T->right == NULL)
{
delete T;
return NULL;
}
else if (T->right == NULL)
{
current = T->left;
delete T;
T = current;
}
else if (T->left == NULL)
{
current = T->right;
delete T;
T = current;
}
else
{
current = max (T->left); //replace the node with the maximum on the left or the minimum on the right and then erase that node
T->data = current->data;
T->count = current->count;
current->count = 0;
search_value = current->data;
T->left = erase (T->left);
}
}
}
else if (search_value < T->data)
{
T->left = erase (T->left);
}
else
{
T->right = erase (T->right);
}
T = repair (T);
return T;
}
public:
void erase (TEMPLATE x) //Erases an appearance of x, if there is no such appearance, it will simply not do anything. NOTE: I can update the function to return a value to indicate whether it did something or not
{
search_value = x;
to_erase = 1;
root = erase (root);
}
void erase (TEMPLATE x, int nr) //erases nr objects of value x
{
search_value = x;
if (find(x) >= nr)
{
search_value = x;
to_erase = nr;
root = erase (root);
}
}
//Kth ELEMENT
private:
node<TEMPLATE> *kth_element (node <TEMPLATE> *T)
{
int left_subtree = 0;
if (T->left != NULL)
left_subtree = T->left->subtree;
if (left_subtree == search_value-1)
return T;
else if (left_subtree > search_value-1)
return kth_element (T->left);
else
{
search_value -= left_subtree+1;
return kth_element (T->right);
}
}
public:
TEMPLATE kth_element (int k)
{
if (k > nr_objects)
return bad_signal;
search_value = k;
return kth_element (root) -> data;
}
};
//Possible addition: method to enable traversal of the objects in-order in O(N) (right now it's only possible in O(N*logN))
char s[1<<22];
int p,n,x,y,op,z;
int get_op ()
{
p+=2;
if (s[p-1] == 'I')
return 1;
if (s[p-1] == 'S')
return 2;
if (s[p-1] == 'C')
return 3;
p +=2;
if (s[p-2] == 'A')
return 4;
if (s[p-2] == 'I')
return 5;
return 6;
}
int get_int()
{
++p;
int x = 0;
while (p < n && s[p] != ' ' && s[p] != '\n')
{
x = x*10+(s[p]-'0');
++p;
}
return x;
}
int main()
{
FILE *file = fopen ("zeap.in","r");
fread (s,1,(1<<22),file);
n = strlen(s);
AVL <int> S,dif;
p = -1;
while (p < n)
{
op = get_op ();
if (op == 6)
break;
if (op == 1)
{
x = get_int ();
if (S.find(x))
continue;
S.insert (x);
y = S.next (x);
if (y != 0)
dif.insert (y-x);
z = S.prev (x);
if (z != 0)
dif.insert (x-z);
if (y != 0 && z != 0)
dif.erase (y-z);
}
else if (op == 2)
{
x = get_int ();
if (!S.find (x))
fout<<-1<<"\n";
else
{
y = S.next (x);
if (y != 0)
dif.erase (y-x);
z = S.prev (x);
if (z != 0)
dif.erase (x-z);
if (y != 0 && z != 0)
dif.insert (y-z);
S.erase (x);
}
}
else if (op == 3)
{
x = get_int();
y = S.find (x);
if (y)
fout<<1;
else fout<<0;
fout<<"\n";
}
else if (op == 4)
{
if (S.size() < 2)
{
fout<<-1<<"\n";
}
else fout<<S.max()-S.min()<<"\n";
}
else
{
if (S.size() < 2)
{
fout<<-1<<"\n";
}
else fout<<dif.min()<<"\n";
}
}
}