#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef unsigned long	U16;
typedef 		 char	C08;

#define NUM_STR_MAX	  11					// Contain '\0'
#define OPE_STR_MAX	  (NUM_STR_MAX + 7)
#define OPE_COUNT_MAX 2000000
#define INPUT_NUM_MIN 0
#define INPUT_NUM_MAX 2000000000

static void Insert_Num_Void(U16 *U16_Queue_p, U16 *U16_MaxNum_p, U16 U16_InputNum);								// Function of insert the num to queue
static void Extract_Num_Void(U16 *U16_Queue_p, U16 *U16_MaxNum_p, U16 *U16_QueueStart_p, U16 *U16_QueueEnd_p);	// Function of extract the maximum num of queue


/***********************************************************************************
 ++module <main>
 ++outline
	main function
 ++arguments
	<>			<>					[]
 ++supp
 	<return>
 	  nothing
 ++end_module
************************************************************************************/
int main(void)
{
	// Valiable declaration
	C08 C08_OpeStr[OPE_STR_MAX]   = {'\0'};	// Operation string ("insert XX", "extract", "end")
	C08 C08_InputNum[NUM_STR_MAX] = {'\0'}; // Input num(C08)
	U16 U16_InputNum = 0;					// Input num(U16)
	U16 *U16_Queue_p;						// Queue
	U16 *U16_MaxNum_p;						// Max num address of queue
	U16 *U16_QueueStart_p;					// Address of queue start
	U16 *U16_QueueEnd_p;					// Address of queue end
	C08 *C08_IsOpeStrMatch_p;				// Check the Operation
	U16 U16_i = 0;							// Loop valiable
	
	// Get malloc and set the first address
	U16_Queue_p = (U16 *)malloc(sizeof(U16) * OPE_COUNT_MAX);
	if(NULL == U16_Queue_p)
	{
		return 1;
	}
	U16_MaxNum_p     = U16_Queue_p;
	U16_QueueStart_p = U16_Queue_p;
	U16_QueueEnd_p   = U16_Queue_p;
	
	// Initialize the queue
	for(U16_i = 0; U16_i < OPE_COUNT_MAX; U16_i++)
	{
		*U16_Queue_p = 0;
		U16_Queue_p++;
	}
	
	// memset(U16_MaxNum_p, OPE_COUNT_MAX, 0);
	U16_Queue_p = U16_MaxNum_p;							// Reset the queue address
	U16_i = 0;
	
	// Input the operation
	while(U16_i < OPE_COUNT_MAX)
	{
		fgets(C08_OpeStr, OPE_STR_MAX, stdin);
		
		if( NULL != ( C08_IsOpeStrMatch_p = strstr(C08_OpeStr, "insert") ) )			// Insert the num
		{
			// Get the number from "C08_OpeStr"
			strncpy(C08_InputNum, C08_OpeStr + (OPE_STR_MAX - NUM_STR_MAX), NUM_STR_MAX);
			U16_InputNum = atoi(C08_InputNum);
			
			// If the input num is out of the range, do nothing
			if(INPUT_NUM_MAX < U16_InputNum)
			{
				
			}
			// If the queue is empty, insert the num in top of the queue
			else if(U16_QueueStart_p == U16_QueueEnd_p)
			{
				*U16_Queue_p = U16_InputNum;
				U16_Queue_p++;
				U16_QueueEnd_p = U16_Queue_p;
			}
			else
			{
				// Insert the num
				Insert_Num_Void(U16_Queue_p, U16_MaxNum_p, U16_InputNum);
				U16_QueueEnd_p = U16_Queue_p;
			}
		}
		else if( NULL != ( C08_IsOpeStrMatch_p = strstr(C08_OpeStr, "extract") ) )		// Extract the num
		{
			// If the queue is empty, do nothing
			if(U16_QueueStart_p == U16_QueueEnd_p)
			{
				
			}
			else
			{
				// Extract the num
				Extract_Num_Void(U16_Queue_p, U16_MaxNum_p, U16_QueueStart_p, U16_QueueEnd_p);
			}
		}
		else if( NULL != ( C08_IsOpeStrMatch_p = strstr(C08_OpeStr, "end") ) )			// End
		{
			break;
		}
		else
		{
			// Do nothing
		}
		
		// Reset the operation string
		memset(&C08_OpeStr[0], '\0', sizeof(C08_OpeStr));
		U16_i++;
	}
	
	// Release the queue
	free(U16_Queue_p);
	
	return 0;
}

/***********************************************************************************
 ++module <Insert_Num_Void>
 ++outline
	Insert the num to queue
 ++arguments
	<U16>	<U16_Queue_p>		[Queue pointer]
	<U16>	<U16_MaxNum_p>		[Address of maximim num]
	<U16>	<U16_InputNum>		[Input num]
 ++supp
 	<return>
 	  nothing
 ++end_module
************************************************************************************/
static void Insert_Num_Void(U16 *U16_Queue_p, U16 *U16_MaxNum_p, U16 U16_InputNum)
{
	*U16_Queue_p = U16_InputNum;			// Insert the num
	
	// Update the max num
	if(*U16_Queue_p > *U16_MaxNum_p)
	{
		U16_MaxNum_p = U16_Queue_p;
	}
	
	// Update the end addresss
	U16_Queue_p++;
	
	return;
}


/***********************************************************************************
 ++module <Extract_Num_Void>
 ++outline
	Extract the maximum num of queue
 ++arguments
	<U16>	<U16_Queue_p>		[Queue pointer]
	<U16>	<U16_MaxNum_p>		[Address of maximim num]
	<U16>	<U16_QueueStart_p>	[Address of queue start]
	<U16>	<U16_QueueEnd_p>	[Address of queue end]
 ++supp
 	<return>
 	  nothing
 ++end_module
************************************************************************************/
static void Extract_Num_Void(U16 *U16_Queue_p, U16 *U16_MaxNum_p, U16 *U16_QueueStart_p, U16 *U16_QueueEnd_p)
{
	U16 *U16_QueuePrev_p;
	
	printf("%ld\n", *U16_MaxNum_p);				// Disp the maximim num
	
	// Update the queue
	U16_Queue_p = U16_MaxNum_p;
	while(1)
	{
		U16_QueuePrev_p  = U16_Queue_p;
		U16_Queue_p++;
		*U16_QueuePrev_p = *U16_Queue_p;
		
		if(U16_Queue_p == U16_QueueEnd_p)
		{
			// Update U16_QueueEnd_p
			*U16_Queue_p = 0;
			U16_Queue_p--;
			U16_QueueEnd_p = U16_Queue_p;
			break;
		}
	}
	
	// Update the maximim num
	U16_MaxNum_p = U16_QueueStart_p;
	U16_Queue_p  = ++U16_QueueStart_p;
	
	while(1)
	{
		if(*U16_Queue_p > *U16_MaxNum_p)
		{
			U16_MaxNum_p = U16_Queue_p;
		}
		
		// If "U16_Queue_p" is "U16_QueueEnd_p", break
		// If "U16_Queue_p" is not "U16_QueueEnd_p", update "U16_Queue_p"
		if(U16_Queue_p == U16_QueueEnd_p)
		{
			break;
		}
		else
		{
			U16_Queue_p++;
		}
	}
	
	return;
}

/*
insert 8
insert 2
extract
insert 10
extract
insert 11
extract
extract
end
*/
