PAT Grade --A1057 Stack

Stack is one of the most fundamental data structures, which is based on the principle of Last In First Out (LIFO). The basic operations include Push (inserting an element onto the top position) and Pop (deleting the top element). Now you are supposed to implement a stack with an extra operation: PeekMedian -- return the median value of all the elements in the stack. With N elements, the median value is defined to be the (-th smallest element if N is even, or (-th if N is odd.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤). Then N lines follow, each contains a command in one of the following 3 formats:

Push key
Pop
PeekMedian

where key is a positive integer no more than 1.

Output Specification:

For each Push command, insert key into the stack and output nothing. For each Pop or PeekMediancommand, print in a line the corresponding returned value. If the command is invalid, print Invalidinstead.

Sample Input:

17
Pop
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
Pop
Push 5
Push 4
PeekMedian
Pop
Pop
Pop
Pop

Sample Output:

Invalid
Invalid
3
2
2
1
2
4
4
5
3
Invalid

Array data is constantly being input and deleted, so you real-time feedback median array:
using chunked thinking
1, in general, in order to achieve high efficiency of an ordered sequence of N elements speaking, except the last one, the number of elements in each of the remainder should | √N | (rounded down here, to facilitate program implementation), then the block number [√N] (here, upward Rounding). This put an ordered sequence into [√N] blocks, where the number of elements in each block does not exceed | √N |.
Considering the elements of a sequence of no more than 105 are non-negative integers, arranged so take a hash array table [100001], where Table [x] represents the current number of integer x exists;
Next, block by thinking, logic from 0-10 will be divided into | √ (105 + 1) | = 317 blocks, the number of elements per block 316. Results logically divided into blocks as follows:
0,1,2, ..., 0 for the first 314, 315;.
316, 317 ..., 630, 631 for the first block.
99856,99857, ... 100000 for the first 316.
Such blocking what use is it? Defines a statistical array block [317], where Block [i] represents the number of elements present in the i-th block. So if you want to add an element x, can calculate the first block where the number x is x / 316, and so block [x / 316] plus 1 indicates the number of elements in the block more than 1; the same order table [ x] plus 1, x represents an integer of currently exist
in more than one number.
334, for example, want to add this element, you can by 334/316 = 1 calculates the block number where the element 334 is 1, then allowed to block [1] ++, represents an increase of a number of elements, and so Table [334 ] + 1, 334 indicates the number of elements in the presence of more than 1.
Similarly, if you want to delete an element x, just let block [x / 316] and table [x] will subtract 1. Clearly, the time complexity of the new and delete elements are O (1).
Then look at how the query sequence what K-large elements Yes.
First, from small to large enumeration block number, block the use of the array to obtain accumulated before i - 1 block elements present in the total number and the total number of elements is determined after the addition of the number of block element No. i can achieve K. If so, then the large number of K in the current enumeration of this block, then just ascending through each element of the block (where the first element is the block No. i i * 316) , the number of accumulation continued presence of the array using a table element, until the total cumulative number reaches K, then the sequence of K found in large numbers. Obviously the whole idea is to use O (√N) find the time complexity of K large element in which one, then use 0 (√N) time complexity to find this element in the block, so a single query total time complexity is 0 (√N).

. 1 #include <the iostream>
 2 #include <Stack>
 . 3 #include < String >
 . 4 #include <the cmath>
 . 5  the using  namespace STD;
 . 6  int N, NUM, Table [ 100010 ], Block [ 316 ]; // number of number, the number of the block number 
. 7  int main ()
 . 8  {
 . 9      CIN >> N;
 10      Stack < int > S;
 . 11      String STR;
 12 is      for ( int I = 0 ; I <N; ++i)
13     {
14         cin >> str;
15         if (str == "Pop")
16         {
17             if (s.size() > 0)
18             {
19                 cout << s.top() << endl;
20                 table[s.top()]--;
21                 block[s.top() / 316]--;                
22                 s.pop();
23             }
24             else
25                 cout << "Invalid" << endl;
26         }
27         else if (str == "Push")
28         {
29             cin >> num;
30             s.push(num);
31             table[num]++;
32             block[num / 316]++;
33         }
34         else
35         {
36             if (s.size() > 0)
37             {
38                 int mid = s.size() % 2 == 0 ? s.size() / 2 : (s.size() + 1) / 2;
39                 int t = 0, k = 0;
40                 while (k + block[t] < mid) k += block[t++];
41                 int num = t * 316;
42                 while (k + table[num] < mid)k += table[num++];
43                 cout << num << endl;
44             }
45             else
46                 cout << "Invalid" << endl;
47         }
48     }
49     return 0;    
50 }

 

Guess you like

Origin www.cnblogs.com/zzw1024/p/11291758.html