PAT A 1057 Stack

Stack is one of the most fundamental data structures, which is based on the principle of Last In First Out (LIFO). The basic oper‐ations 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 ele‐ments, the median value is defined to be the -th smallest element if is even, or -th if is odd.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer (). Then 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 .
Output Specification:
For each Push command, insert key into the stack and output nothing. For each Pop or PeekMedian command, print in a line the corresponding returned value. If the command is invalid, print Invalid instead.
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

大意:
Pop:弹出栈顶 并输出(需要判空 空为Invalid)
Push:入栈
PeekMedian:输出中位数(若栈里面的个数为偶数 中位数为第N/2个;若栈里面的个数为奇数 中位数为第N/2 + 1个)
怎么计算这个中位数???(且不能TLE)
分块。。。
将N(1e5)分成sqrt(N)块 :316
遍历的时候直接遍历块 先看看这个块中存了多少数字
直到遍历到超过等于中位数的块
再单独遍历这个块中的数字出现的个数
直到遍历到超过等于中位数的数字个数
则就是这个数字

代码:

#include 
#include 
#include 

using namespace std;

int n;
const int N = 1e5+10;
int q[N];
int t;
int num;
int cnt[N];
int block[N];
const int sqrtN = 316;//sqrt(N) 每一块存的个数

int main()
{
    cin>>n;
    while(n--)
    {
        string op;
        cin>>op;
        if(op == "Pop")
        {
            if(t == 0) puts("Invalid");
            else
            {
                cout<<q[t]<<endl;
                cnt[q[t]]--;
                block[q[t]/sqrtN]--;
                t--;
                num--;
            }
        }
        else if(op == "Push")
        {
            int x;
            cin>>x;
            q[++t] = x; 
            cnt[x]++;
            block[x/sqrtN]++;
            num++;
        }
        else
        {
            if(t == 0) puts("Invalid");
            else
            {
                //确定中位数位置
                int idx = 0;
                if(num % 2 == 0) idx = num/2;
                else idx = num/2 + 1;
                
                int i = 0;//i是第几块
                int summ = 0;//summ累计个数 直到加上某个块的个数>idx停
                while(summ + block[i] < idx)
                {
                    summ += block[i];
                    i++;
                }
                int x = i * sqrtN;//第i块的第一个数
                //summ累加这个块中的出现的数字出现的个数
                while(summ + cnt[x] < idx)
                {
                    summ += cnt[x];
                    x++;
                }
                cout<<x<<endl;
            }
        }
    }
    return 0;
}

推荐歌曲:《好想我回来啊》-华晨宇 网易云

你可能感兴趣的:(PAT A 1057 Stack)