Cod sursa(job #3246357)

Utilizator Ilie_MityIlie Dumitru Ilie_Mity Data 2 octombrie 2024 19:44:08
Problema Hashuri Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.86 kb
// Ilie "The-Winner" Dumitru
#include<cstdio>
#include<cassert>
#include<random>
typedef unsigned int ui;
typedef unsigned long long ull;

ull hash(ui x)
{
	ull offset=0xcbf29ce484222325ULL;
	ull prime=0x100000001b3ULL;

	for(int i=0;i<4;++i)
	{
		offset^=x&0xffU;
		x>>=8;
		offset*=prime;
	}

	return offset;
}

struct LNode
{
	ui x;
	LNode* next;

	LNode() : x(0), next(0) {}
	LNode(ui x) : x(x), next(0) {}
	LNode(ui x, LNode* next) : x(x), next(next) {}
};

const int HTblPs[]={5, 11, 29, 61, 127, 307, 907, 2003, 5021, 10007, 25013, 50021, 100019, 250007, 500009, 1000003, 3000017, 10000019};
const int HTblPsCnt=sizeof(HTblPs)/sizeof(*HTblPs);

struct HTbl
{
	int sz;
	int cap;
	LNode** v;

	HTbl() : sz(0), cap(-1), v(0) {}
	HTbl(const HTbl& other) = delete;
	~HTbl() {delete v;}

	void insert(ui x)
	{
		if(find(x))
			return;

		if(cap==-1 || (sz>=HTblPs[cap]*2 && cap+1<HTblPsCnt))
		{
			++cap;
			realloc(cap-1);
		}

		ull h=hash(x)%HTblPs[cap];
		v[h]=new LNode(x, v[h]);
		++sz;
	}

	bool find(ui x)
	{
		if(cap==-1)
			return 0;

		ull h=hash(x)%HTblPs[cap];
		return find(v[h], x);
	}

	void erase(ui x)
	{
		if(cap==-1)
			return;

		ull h=hash(x)%HTblPs[cap];
		erase(v[h], x);
	}

	void print()
	{
		for(int i=0;i<HTblPs[cap];++i)
		{
			printf("%d:", i);
			for(LNode* p=v[i];p;p=p->next)
				printf(" %d", p->x);
			printf("\n");
		}
	}

private:
	void erase(LNode*& p, ui x)
	{
		if(p==0)
			return;
		if(p->x==x)
		{
			--sz;
			LNode* aux=p;
			p=p->next;
			delete aux;
			if(sz==0 || (cap && HTblPs[cap]/2>=sz))
			{
				--cap;
				realloc(cap+1);
			}
		}
		else
			return erase(p->next, x);
	}

	bool find(LNode* p, ui x)
	{
		while(p && p->x!=x)
			p=p->next;
		return p;
	}

	void realloc(int prevCap)
	{
		if(prevCap==-1)
		{
			if(!v)
			{
				v=new LNode*[HTblPs[cap]];
				for(int i=0;i<HTblPs[cap];++i)
					v[i]=0;
			}
			return;
		}

		if(cap==-1)
			return;

		LNode** nv=new LNode*[HTblPs[cap]];
		for(int i=0;i<HTblPs[cap];++i)
			nv[i]=0;
		for(int i=0;i<HTblPs[prevCap];++i)
		{
			while(v[i])
			{
				LNode* aux=v[i];
				v[i]=v[i]->next;
				ull h=hash(aux->x)%HTblPs[cap];
				aux->next=nv[h];
				nv[h]=aux;
			}
		}

		delete[] v;
		v=nv;
	}
};

void test_01()
{
	HTbl H;
	int i, j, N=100;

	for(i=0;i<N;++i)
	{
		H.insert(i);

		for(j=0;j<N;++j)
			assert((j<=i)==(H.find(j)));

		H.print();
	}

	for(i=0;i<N;++i)
		H.erase(i);
}

void test_02()
{
	HTbl H;
	int i, N=100000;
	std::mt19937 rng(hash(1335857393));

	for(i=0;i<N;++i)
		printf("%d\n", i), fflush(stdout), H.insert(std::uniform_int_distribution<>(0, 1000000000)(rng));
}

int main(int argc, char* argv[])
{
	// test_01();
	// test_02();

	HTbl H;
	int i, op, x;
	freopen("hashuri.in", "r", stdin);
	freopen("hashuri.out", "w", stdout);

	scanf("%d", &i);
	do
	{
		scanf("%d%d", &op, &x);
		if(op==1)
			H.insert(x);
		else if(op==2)
			H.erase(x);
		else
			printf("%d\n", (int)H.find(x));
	}while(--i);

	return 0;
}