Cod sursa(job #2083106)

Utilizator RazvanR104Razvan-Andrei Ciocoiu RazvanR104 Data 7 decembrie 2017 03:15:05
Problema Hashuri Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 6.32 kb
#include <bits/stdc++.h>

using namespace std;

const int BFACTOR = 5;

struct Node {
	int size;
	int keys[2 * BFACTOR];
	Node *child[2 * BFACTOR];
	Node(Node *nil = nullptr):
		size(0) {
		child[0] = nil;
	}
};

void splitChild(Node *father, int index) {
	Node *left = father->child[index];
	Node *right = new Node(nullptr);
	left->size = right->size = BFACTOR - 1;
	for (int i = BFACTOR; i < 2 * BFACTOR - 1; ++i) {
		right->keys[i - BFACTOR] = left->keys[i];
		right->child[i - BFACTOR] = left->child[i];
	}
	right->child[BFACTOR - 1] = left->child[2 * BFACTOR - 1];
	for (int i = father->size - 1; i >= index; --i)
		father->keys[i + 1] = father->keys[i];
	for (int i = father->size; i >= index + 1; --i)
		father->child[i + 1] = father->child[i];
	father->keys[index] = left->keys[BFACTOR - 1];
	father->child[index] = left;
	father->child[index + 1] = right;
	++father->size;
	if (left->child[0] == nullptr)
		right->child[0] = nullptr;
}

void _insertValue(Node *curr, int value) {
	int pos = 0;
	while (pos < curr->size && value > curr->keys[pos])
		++pos;
	if (pos < curr->size && value == curr->keys[pos])
		return;
	if (curr->child[0] == nullptr) {
		for (int i = curr->size; i >= pos; --i)
			curr->keys[i + 1] = curr->keys[i];
		curr->keys[pos] = value;
		++curr->size;
		return;
	}
	if (curr->child[pos]->size == 2 * BFACTOR - 1) {
		splitChild(curr, pos);
		if (value < curr->keys[pos])
			_insertValue(curr->child[pos], value);
		else
			_insertValue(curr->child[pos + 1], value);
		return;
	}
	_insertValue(curr->child[pos], value);
}

Node *insertValue(Node *root, int value) {
	if (root->size == 2 * BFACTOR - 1) {
		Node *newRoot = new Node(root);
		splitChild(newRoot, 0);
		_insertValue(newRoot, value);
		return newRoot;
	}
	_insertValue(root, value);
	return root;
}

int countValue(Node *curr, int value) {
	int pos = 0;
	while (pos < curr->size && value > curr->keys[pos])
		++pos;
	if (pos < curr->size && value == curr->keys[pos])
		return true;
	if (curr->child[0] == nullptr)
		return false;
	return countValue(curr->child[pos], value);
}

int lastLevel = -1;
int dfsCheck(Node *curr, int level) {
	if (curr->child[0] == nullptr) {
		if (lastLevel != -1 && lastLevel != level)
			return 0;
		lastLevel = level;
		return 1;
	}
	int answer = 1;
	for (int i = 0; i <= curr->size; ++i)
		answer = min(answer, dfsCheck(curr->child[i], level + 1));
	return answer;
}

void moveKeyLeft(Node *father, int index) {
	Node *left = father->child[index - 1];
	Node *right = father->child[index];
	for (int i = right->size - 1; i >= 0; --i)
		right->keys[i + 1] = right->keys[i];
	for (int i = right->size; i >= 0; --i)
		right->child[i + 1] = right->child[i];
	right->keys[0] = father->keys[index - 1];
	right->child[0] = left->child[left->size];
	father->keys[index - 1] = left->keys[left->size - 1];
	--left->size;
	++right->size;
	if (right->child[1] == nullptr)
		right->child[0] = nullptr;
}

void moveKeyRight(Node *father, int index) {
	Node *left = father->child[index];
	Node *right = father->child[index + 1];
	left->keys[left->size] = father->keys[index];
	left->child[left->size + 1] = right->child[0];
	father->keys[index] = right->keys[0];
	for (int i = 0; i < right->size - 1; ++i)
		right->keys[i] = right->keys[i + 1];
	for (int i = 0; i < right->size; ++i)
		right->child[i] = right->child[i + 1];
	++left->size;
	--right->size;
	if (left->child[left->size] == nullptr)
		right->child[0] = nullptr;
}

Node *lowerKey(Node *father, int index) {
	Node *left = father->child[index];
	Node *right = father->child[index + 1];
	left->keys[left->size] = father->keys[index];
	for (int i = 0; i < BFACTOR; ++i)
		left->keys[left->size + i + 1] = right->keys[i];
	for (int i = BFACTOR; i < 2 * BFACTOR; ++i)
		left->child[i] = right->child[i - BFACTOR];
	for (int i = index; i < father->size - 1; ++i)
		father->keys[i] = father->keys[i + 1];
	for (int i = index + 1; i < father->size; ++i)
		father->child[i] = father->child[i + 1];
	--father->size;
	left->size = 2 * BFACTOR - 1;
	delete right;
	return left;
}

int treeMinimum(Node *curr) {
	if (curr->child[0] == nullptr)
		return curr->keys[0];
	return treeMinimum(curr->child[0]);
}

int treeMaximum(Node *curr) {
	if (curr->child[0] == nullptr)
		return curr->keys[curr->size - 1];
	return treeMaximum(curr->child[curr->size]);
}

void _deleteValue(Node *curr, int value) {
	int pos = 0;
	while (pos < curr->size && value > curr->keys[pos])
		++pos;
	if (pos < curr->size && value == curr->keys[pos]) {
		if (curr->child[0] == nullptr) {
			for (int i = pos; i < curr->size - 1; ++i)
				curr->keys[i] = curr->keys[i + 1];
			--curr->size;
			return;
		}
		if (curr->child[pos]->size >= BFACTOR) {
			curr->keys[pos] = treeMaximum(curr->child[pos]);
			_deleteValue(curr->child[pos], curr->keys[pos]);
			return;
		}
		if (curr->child[pos + 1]->size >= BFACTOR) {
			curr->keys[pos] = treeMinimum(curr->child[pos + 1]);
			_deleteValue(curr->child[pos + 1], curr->keys[pos]);
			return;
		}
		Node *next = lowerKey(curr, pos);
		_deleteValue(next, value);
	} else if (curr->child[0] == nullptr)
		return;
	if (curr->child[pos]->size == BFACTOR - 1) {
		if (pos - 1 >= 0 && curr->child[pos - 1]->size >= BFACTOR)
			moveKeyLeft(curr, pos);
		else if (pos + 1 <= curr->size && curr->child[pos + 1]->size >= BFACTOR)
			moveKeyRight(curr, pos);
		else {
			if (pos + 1 <= curr->size) {
				_deleteValue(lowerKey(curr, pos), value);
				return;
			} else {
				_deleteValue(lowerKey(curr, pos - 1), value);
				return;
			}
		}
	}
	_deleteValue(curr->child[pos], value);
}

Node *deleteValue(Node *root, int value) {
	if (root->size == 1 && root->child[0]->size == BFACTOR - 1 && root->child[1]->size == BFACTOR - 1) {
		Node *newRoot = lowerKey(root, 0);
		_deleteValue(newRoot, value);
		return newRoot;
	}
	_deleteValue(root, value);
	return root;
}

int main() {
	assert(freopen("hashuri.in", "r", stdin));
	assert(freopen("hashuri.out", "w", stdout));

	Node *root = new Node();
	root->child[0] = nullptr;

	int N;
	scanf("%d", &N);
	while (N--) {
		int op, x;
		scanf("%d %d", &op, &x);
		if (op == 1)
			root = insertValue(root, x);
		else if (op == 2)
			root = deleteValue(root, x);
		else
			cout << countValue(root, x) << '\n';
	}

	return 0;
}