Cod sursa(job #940904)

Utilizator radustn92Radu Stancu radustn92 Data 17 aprilie 2013 13:49:02
Problema Nums Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.84 kb
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <iostream>
#define pb push_back
using namespace std;

struct entry
{
	string nr;
	entry *left, *right;
	int total, depth;
	
	entry()
	{
		left = right = NULL;
		total = 0;
		depth = 0;
	}
};
entry *root = new entry();
int n, k, limit;
string curr;
vector <string> list;

inline int comp(string s1, string s2)
{
	if (s1.size() < s2.size())
		return 1;
	if (s1.size() > s2.size())
		return 0;
	return s1 < s2;
}

void add(entry *node)
{
	if (node -> total == 0)
	{
		node -> nr = curr;
		node -> total = 1;
		node -> depth = 1;
		return ;
	}
	
	if ((node -> nr).compare(curr) == 0)
		return ;
	
	if (!comp(node -> nr, curr))
	{
		if (node -> left == NULL)
			node -> left = new entry();
		add(node -> left);
	}
	else
	{
		if (node -> right == NULL)
			node -> right = new entry();
		add(node -> right);
	}
	
	int sons = 1, maxDepth = 0;
	if (node -> left != NULL)
	{
		sons += node -> left -> total;
		maxDepth = max(maxDepth, node -> left -> depth);
	}
	if (node -> right != NULL)
	{
		sons += node -> right -> total;
		maxDepth = max(maxDepth, node -> right -> depth);
	}
	node -> total = sons;
	node -> depth = maxDepth + 1;
}

string search(entry *node)
{
	if (node -> left != NULL)
	{
		if (node -> left -> total >= k)
			return search(node -> left);
		k -= node -> left -> total;
	}
	
	if (k == 1)
		return node -> nr;
	k--;
	
	return search(node -> right);
}

void getNodes(entry *node)
{
	if (node -> left != NULL)
		getNodes(node -> left);
	
	list.pb(node -> nr);
	
	if (node -> right != NULL)
		getNodes(node -> right);
	
	delete node;
}

void remake(int left, int right, entry *node)
{
	int mid = (left + right) >> 1;
	node -> nr = list[mid - 1];
	node -> depth = 1;
	node -> total = 1;
	
	if (mid > left)
	{
		node -> left = new entry();
		remake(left, mid - 1, node -> left);
	}
	if (mid < right)
	{
		node -> right = new entry();
		remake(mid + 1, right, node -> right);
	}
	
	int sons = 1, maxDepth = 0;
	if (node -> left != NULL)
	{
		sons += node -> left -> total;
		maxDepth = max(maxDepth, node -> left -> depth);
	}
	if (node -> right != NULL)
	{
		sons += node -> right -> total;
		maxDepth = max(maxDepth, node -> right -> depth);
	}
	node -> total = sons;
	node -> depth = maxDepth + 1;
}

int main()
{
	freopen("nums.in", "r", stdin);
	freopen("nums.out", "w", stdout);
	cin >> n;
	limit = (int)sqrt(n);
	
	int i, tip;
	for (i = 1; i <= n; i++)
	{
		cin >> tip;
		if (tip == 1)
		{
			cin >> curr;
			add(root);
			
			if (root -> depth > limit)
			{
				list.clear();
				getNodes(root);
				root = new entry();
				remake(1, list.size(), root);
			}
		}
		else
		{
			cin >> k;
			cout << search(root) << '\n';
		}
	}
	return 0;
}