// Balcau Ionut, gupa 134 - cukoo hash cu functii virtuale
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
class baseHash
{
protected:
uint *hash1,*hash2;
uint a1,a2,b1,b2,size,m1,m2;
public:
baseHash(uint n);
virtual ~baseHash();
void init();
void setParams();
virtual void solveHashuri()=0;
virtual uint h1(uint &)=0;
virtual uint h2(uint &)=0;
virtual bool comp(uint, uint)=0;
bool operator += (uint);
void operator -= (uint);
bool operator == (uint);
};
baseHash::baseHash(uint n)
{
size=n;
hash1 = new uint[size];
hash2 = new uint[size];
}
baseHash::~baseHash()
{
delete[] hash1;
delete[] hash2;
}
void baseHash::setParams()
{
a1 = rand() % size;
b2 = rand() % size;
a2 = rand() % size;
b1 = rand() % size;
m1 = size - size/10 + rand() % size/10;
m2 = size - size/10 + rand() % size/10;
}
bool baseHash::operator+=(uint index)
{
uint nr=0, i1, i2, aux;
i1 = h1(index);
i2 = h2(index);
if( (comp(hash1[i1],index)) || ( comp(hash2[i2],index)) )
return true;
if(hash1[i1]==0)
{
hash1[i1]=index;
return true;
}
else
if(hash2[i2]==0)
{
hash2[i2]=index;
return true;
}
else
{
aux = index;
index = hash1[i1];
hash1[i1] = aux;
}
while(nr<30)
{
nr++;
i2 = h2(index);
if(hash2[i2]==0)
{
hash2[i2]=index;
return true;
}
else
{
i1 = h1(hash2[i2]);
aux=hash2[i2];
hash2[i2]=index;
index=hash1[i1];
hash1[i1]=aux;
}
}
return false;
}
void baseHash::operator-=(uint index)
{
uint i1, i2;
i1 = h1(index);
i2 = h2(index);
if( comp(hash1[i1],index))
hash1[i1]=0;
else
if( comp(hash2[i2],index))
hash2[i2] = 0;
}
bool baseHash::operator==(uint index)
{
uint i1, i2;
i1 = h1(index);
i2 = h2(index);
if( comp( hash1[i1], index ) || comp( hash2[i2], index ))
return 1;
else
return 0;
}
void baseHash::init()
{
fill(hash1,hash1+size,0);
fill(hash2,hash2+size,0);
setParams();
}
class intHash:public baseHash
{
int *v;
public:
intHash(uint size):baseHash(size)
{
v=new int[size+1];
}
~intHash(){ delete[] v;}
void solveHashuri();
uint h1(uint &);
uint h2(uint &);
bool comp(uint, uint);
};
void intHash::solveHashuri()
{
uint n, op, i, ok=0;
while(ok==0)
{
init();
ifstream f("hashuri.in");
ofstream g("hashuri.out");
f>>n;
ok=1;
for(i=1; i <= n && ok; i++)
{
f>>op>>v[i];
if(op==1)
ok = *this += i;
else
if(op==2)
*this -= i;
else
g<<(*this==i)<<"\n";
}
f.close();
g.close();
}
}
uint intHash::h1(uint &index)
{
uint poz;
poz=((a1 + b1*v[index] ) % m1) % size;
return poz;
}
uint intHash::h2(uint &index)
{
uint poz;
poz=((a2 + b2*v[index] ) % m2) % size;
return poz;
}
bool intHash::comp(uint x, uint y)
{
if(v[x]==v[y])
return 1;
else
return 0;
}
class uintHash:public baseHash
{
uint *v;
public:
uintHash(uint size):baseHash(size)
{
v=new uint[size+1];
}
~uintHash(){ delete[] v;}
void solveHashuri();
uint h1(uint &);
uint h2(uint &);
bool comp(uint, uint);
};
void uintHash::solveHashuri()
{
uint n, op, i, ok=0;
while(ok==0)
{
init();
ifstream f("hashuri.in");
ofstream g("hashuri.out");
f>>n;
ok=1;
for(i=1; i <= n && ok; i++)
{
f>>op>>v[i];
if(op==1)
ok = *this += i;
else
if(op==2)
*this -= i;
else
g<<(*this==i)<<"\n";
}
f.close();
g.close();
}
}
uint uintHash::h1(uint &index)
{
uint poz;
poz=((a1 + b1*v[index] ) % m1) % size;
return poz;
}
uint uintHash::h2(uint &index)
{
uint poz;
poz=((a2 + b2*v[index] ) % m2) % size;
return poz;
}
bool uintHash::comp(uint x, uint y)
{
if(v[x]==v[y])
return 1;
else
return 0;
}
class stringHash: public baseHash
{
string *v;
public:
stringHash(uint size):baseHash(size)
{
v=new string[size+1];
}
~stringHash(){delete[] v;}
void solveHashuri();
uint h1(uint &);
uint h2(uint &);
bool comp(uint, uint);
};
void stringHash::solveHashuri()
{
uint n, op, i, ok=0;
while(ok==0)
{
init();
ifstream f("hashuri.in");
ofstream g("hashuri.out");
f>>n;
ok=1;
for(i=1; i <= n && ok; i++)
{
f>>op>>v[i];
if(op==1)
ok = *this += i;
else
if(op==2)
*this -= i;
else
g<<(*this==i)<<"\n";
}
f.close();
g.close();
}
}
uint stringHash::h1(uint &index)
{
uint aux = 0;
for (uint i =0;i<v[index].size();i++)
aux = (aux+a1 + b1*v[index][i])%size;
return aux;
}
uint stringHash::h2(uint &index)
{
uint aux = 0;
for (uint i =0;i<v[index].size();i++)
aux = (aux+a2 + b2*v[index][i])%size;
return aux;
}
bool stringHash::comp(uint x, uint y)
{
if(v[x]==v[y])
return 1;
else
return 0;
}
class doubleHash:public baseHash
{
double *v;
public:
doubleHash(uint size):baseHash(size)
{
v=new double[size+1];
}
~doubleHash(){ delete[] v;}
void solveHashuri();
uint h1(uint &);
uint h2(uint &);
bool comp(uint, uint);
};
void doubleHash::solveHashuri()
{
uint n, op, i, ok=0;
while(ok==0)
{
init();
ifstream f("hashuri.in");
ofstream g("hashuri.out");
f>>n;
ok=1;
for(i=1; i <= n && ok; i++)
{
f>>op>>v[i];
if(op==1)
ok = *this += i;
else
if(op==2)
*this -= i;
else
g<<(*this==i)<<"\n";
}
f.close();
g.close();
}
}
uint doubleHash::h1(uint &index)
{
uint poz;
while ((v[index]- int(v[index])) != 0)
{
v[index] *= 10;
if (v[index] > size)
{
v[index] -= size;
}
}
poz = (((uint)a1 + (uint)b1*(uint)v[index] ) % (uint)m1) % (uint)size;
return poz;
}
uint doubleHash::h2(uint &index)
{
int poz;
while ((v[index] - int(v[index])) != 0)
{
v[index] *= 10;
if (v[index] > size)
{
v[index] -= size;
}
}
poz = (((uint)a2 + (uint)b2*(uint)v[index] ) % (uint)m2) % (uint)size;
return poz;
}
bool doubleHash::comp(uint x, uint y)
{
if(v[x]==v[y])
return 1;
else
return 0;
}
class floatHash:public baseHash
{
float *v;
public:
floatHash(uint size):baseHash(size)
{
v=new float[size+1];
}
~floatHash(){ delete[] v;}
void solveHashuri();
uint h1(uint &);
uint h2(uint &);
bool comp(uint, uint);
};
void floatHash::solveHashuri()
{
uint n, op, i, ok=0;
while(ok==0)
{
init();
ifstream f("hashuri.in");
ofstream g("hashuri.out");
f>>n;
ok=1;
for(i=1; i <= n && ok; i++)
{
f>>op>>v[i];
if(op==1)
ok = *this += i;
else
if(op==2)
*this -= i;
else
g<<(*this==i)<<"\n";
}
f.close();
g.close();
}
}
uint floatHash::h1(uint &index)
{
uint poz;
while ((v[index] - int(v[index])) != 0)
{
v[index] *= 10;
if (v[index] > size)
{
v[index] -= size;
}
}
poz = (((uint)a1 + (uint)b1*(uint)v[index] ) % (uint)m1) % (uint)size;
return poz;
}
uint floatHash::h2(uint &index)
{
int poz;
while ((v[index] - int(v[index])) != 0)
{
v[index] *= 10;
if (v[index] > size)
{
v[index] -= size;
}
}
poz = (((uint)a2 + (uint)b2*(uint)v[index] ) % (uint)m2) % (uint)size;
return poz;
}
bool floatHash::comp(uint x, uint y)
{
if(v[x]==v[y])
return 1;
else
return 0;
}
int main()
{
srand(time(NULL));
baseHash *h;
// cin>>x;
int x=2;
switch(x){
case 1 : h = new uintHash(1000001); break;
case 2 : h = new intHash(1000001); break;
case 3 : h = new floatHash(1000001); break;
case 4 : h = new doubleHash(1000001); break;
case 5 : h = new stringHash(1000001);
}
h->solveHashuri();
return 0;
}