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

typedef unsigned int	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
#define QUEUE_TOP_IDX	0

static void Insert_Num_Void(U16 *U16_Queue_p, U16 *U16_MaxNumIdx, U16 *U16_QueueEndIdx, U16 U16_InputNum);		// Function of insert the num to queue
static void Extract_Num_Void(U16 *U16_Queue_p, U16 *U16_MaxNumIdx, U16 *U16_QueueEndIdx);       				// 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_MaxNumIdx	= QUEUE_TOP_IDX;	// Max num index of queue
	U16 U16_QueueEndIdx	= QUEUE_TOP_IDX;	// Index of queue end
	C08 *C08_IsOpeStrMatch_p;				// Check the Operation
	U16 U16_i = 0;							// Loop valiable
	
	// Get malloc
	U16_Queue_p = (U16 *)malloc(sizeof(U16) * OPE_COUNT_MAX);
	if(NULL == U16_Queue_p)
	{
		return 1;
	}
	
	// Initialize the queue
	memset(&U16_Queue_p[QUEUE_TOP_IDX], 0, sizeof(U16) * OPE_COUNT_MAX);
	
	// 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)
			{
				
			}
			else
			{
				// Insert the num
				Insert_Num_Void(&U16_Queue_p[QUEUE_TOP_IDX], &U16_MaxNumIdx, &U16_QueueEndIdx, U16_InputNum);
			}
		}
		else if( NULL != ( C08_IsOpeStrMatch_p = strstr(C08_OpeStr, "extract") ) )			// Extract the num
		{
			// If the queue is empty, do nothing
			if(QUEUE_TOP_IDX == U16_QueueEndIdx)
			{
				
			}
			else
			{
				// Extract the num
				Extract_Num_Void(&U16_Queue_p[QUEUE_TOP_IDX], &U16_MaxNumIdx, &U16_QueueEndIdx);
			}
		}
		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]
	<U16>   <U16_MaxNumIdx>	 [Index of maximim num]
	<U16>   <U16_QueueEndIdx>       [Index of queue end]
	<U16>   <U16_InputNum>	  [Input num]
 ++supp
	 <return>
	   nothing
 ++end_module
************************************************************************************/
static void Insert_Num_Void(U16 *U16_Queue_p, U16 *U16_MaxNumIdx, U16 *U16_QueueEndIdx, U16 U16_InputNum)
{
	U16_Queue_p[*U16_QueueEndIdx] = U16_InputNum;		   // Insert the num
	
	// Update the max num
	if(U16_InputNum > U16_Queue_p[*U16_MaxNumIdx])
	{
		*U16_MaxNumIdx = *U16_QueueEndIdx;
	}
	
	// Update the end index
	(*U16_QueueEndIdx)++;
	
	return;
}


/***********************************************************************************
 ++module <Extract_Num_Void>
 ++outline
	Extract the maximum num of queue  ++arguments
	<U16>   <U16_Queue_p>	   [Queue pointer]
	<U16>   <U16_MaxNumIdx>	 [Index of maximim num]
	<U16>   <U16_QueueEndIdx>       [Index of queue end]
 ++supp
	 <return>
	   nothing
 ++end_module
************************************************************************************/
static void Extract_Num_Void(U16 *U16_Queue_p, U16 *U16_MaxNumIdx, U16 *U16_QueueEndIdx)
{
	U16 U16_i;
	
	printf("%d\n", U16_Queue_p[*U16_MaxNumIdx]);				// Disp the max num
	
	// If the queue is empty, return
	if(*U16_QueueEndIdx == QUEUE_TOP_IDX + 1)
	{
		U16_Queue_p[*U16_MaxNumIdx] = 0;
		(*U16_MaxNumIdx)--;
		(*U16_QueueEndIdx)--;
		return;
	}
	
	// Update the queue
	U16_i = (*U16_MaxNumIdx) + 1;
	while(1)
	{
		U16_Queue_p[U16_i - 1] = U16_Queue_p[U16_i];
		
		if(U16_i >= (*U16_QueueEndIdx) - 1)
		{
			// Update the queue end
			U16_Queue_p[U16_i] = 0;
			(*U16_QueueEndIdx)--;
			break;
		}
		U16_i++;
	}
	
	// If the Queue element is only one, return
	if(*U16_QueueEndIdx == QUEUE_TOP_IDX + 1)
	{
		*U16_MaxNumIdx = QUEUE_TOP_IDX;
		return;
	}
	
	// Update the maximim num
	*U16_MaxNumIdx = QUEUE_TOP_IDX;
	U16_i		   = QUEUE_TOP_IDX + 1;
	
	while(1)
	{
		if(U16_Queue_p[U16_i] > U16_Queue_p[*U16_MaxNumIdx])
		{
			*U16_MaxNumIdx = U16_i;
		}
		
		U16_i++;
		
		// If "U16_i" is "U16_QueueEndIdx", break
		// If "U16_i" is not "U16_QueueEndIdx", do nothing
		if(U16_i == (*U16_QueueEndIdx))
		{
			break;
		}
		else
		{
			
		}
	}
	
	return;
}


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

