PAT (Advanced Level) Practice 1057 Stack

Posted Keep--Silent

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PAT (Advanced Level) Practice 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 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 NNN elements, the median value is defined to be the (N/2)(N/2)(N/2)-th smallest element if NNN is even, or ((N+1)/2)((N+1)/2)((N+1)/2)-th if NNN is odd.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer NNN (≤105\\le 10^5105). Then NNN 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 10510^5105.

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

   
    
     
      
     
    
   

大意说明

三种操作:

  • 插入x
  • 删除x
  • 查询中位数

解题思路

数据大小 1 0 5 10^5 105,所以放弃,所以需要一些特定的结构,需要单次插入删除查询三种操作的复杂度必须小于 n n n,才能使得总体复杂度不超过 n 2 n^2 n2,所以选择树状数组。

插入与删除

const int Size = 1e5 + 10;
int vt[Size], n = Size - 5;;
int lb(int x)  return x & (-x); 
void update(int x,int size) 
    for (int i = x; i <= n; i+=lb(i)) 
        vt[i]+=size;
    

  • 插入x: update(x,1);
  • 删除x: update(x,-1);

所以:

  • 插入x
  • 删除x
  • 查询中位数

查询中位数

树状数组表示的是前缀和,我们用vt存储数量 ,二分查找即可: 即我们要查找的是中位数,即查找第一个大于等于一半数量的位置

int getsum(int index) 
    int cnt = 0;
    for (int i = index; i; i -= lb(i))cnt += vt[i];
    return cnt;

void Medeian() 
    int cnt = getsum(n);
    int pot = (cnt+1) / 2;
    if (cnt== 0) 
        printf("Invalid\\n");
        return;
    
    int l = 1, r = n;
    while (l < r) 
        int mid = l + r >> 1;
        if (getsum(mid) >= pot)r = mid;
        else l = mid + 1;
    
    printf("%d\\n",l);

至此

  • 插入x
  • 删除x
  • 查询中位数

复杂度分析

二分复杂度 log ⁡ n \\log n logn,getsum复杂度 log ⁡ n \\log n logn,总共 n n n次操作 ,即总体复杂度 n log ⁡ 2 n n \\log^2 n nlog2n

完整代码

#include <bits/stdc++.h>
using namespace std;

const int Size = 1e5 + 10;

int vt[Size], n = Size - 5;;
int lb(int x)  return x & (-x); 
void update(int x,int size) 
    for (int i = x; i <= n; i+=lb(i)) 
        vt[i]+=size;
    

int getsum(int index) 
    int cnt = 0;
    for (int i = index; i; i -= lb(i))cnt += vt[i];
    return cnt;

void Medeian() 
    int cnt = getsum(n);
    int pot = (cnt+1) / 2;
    if (cnt== 0) 
        printf("Invalid\\n");
        return;
    
    int l = 1, r = n;
    while (l < r) 
        int mid = l + r >> 1;
        if (getsum(mid) >= pot)r = mid;
        else l = mid + 1;
    
    printf("%d\\n",l);


int  main() 
    stack<int>sk;
    int n,x;
    cin >> n;
    char ss[300];
    while (n--) 
        scanf("%s", &ss);
        if (ss[1] == 'o') 
            if (sk.size() == 0) 
                printf("Invalid\\n");
                continue;
            
            x = sk.top();  
            update(x, -1);
            sk.pop();
            printf("%d\\n", x);
        
        else  if (ss[1] == 'u') 
            scanf("%d", &x);
            sk.push(x);
            update(x, 1);
        
        else 
            Medeian();
        
    
	return 0;

以上是关于PAT (Advanced Level) Practice 1057 Stack的主要内容,如果未能解决你的问题,请参考以下文章

PAT Advanced Level 1043

PAT Advanced Level 1079

PAT Advanced Level 1095

PAT Advanced Level 1038

pat advanced level 1063

PAT Advanced level 1003 Emergency