• 【PAT(甲级)】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 N elements, the median value is defined to be the (N/2)-th smallest element if N is even, or ((N+1)/2)-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 (≤10^{5}). 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 10^{5}.

    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

    解题思路:

    1. 对树状数组最好要有个概念,详细的解释我推荐这个博主,他写的真的好https://blog.csdn.net/flushhip/article/details/79165701

    2. 这道题目意思就是要求你给栈增加一个功能,能返回栈内第(N/2)或((N+1)/2)个最小的元素。如果每次都进行排序再输出中间的数字,那么时间上肯定就是超时的。所以,我们把栈内的数字看成是下标,用一个新的数组c[]来存储小于等于这个数字的个数。

    新的数组c[ ]是一个树状数组,树状数组的特点就是可以求某一个区间的前缀和,所以每次只要把下标 i 跳到 i 加减 lowbit(i)的位置就可以清楚的知道关于此数字,有多少个小于等于它的数字存在。

    因为每次更新树状数组的时候,都是以栈内元素为下标的,所以栈内元素一定是符合第(N/2)或(N+1)/2个中最小的一个值。

    代码:

    1. #include
    2. #include
    3. #define max 100001
    4. using namespace std;
    5. int c[max]={0};//用来存储比下标小的数字的个数
    6. stack<int> r;//用来存储给的数字
    7. int lowbit(int a){//树状数组所需要的下标换算
    8. return a&(-a);
    9. }
    10. void update(int x,int k){
    11. //x为输入的值也就是c数组下标,增加k就是1,减少k就是-1
    12. for(int i = x;i < max;i += lowbit(i)){
    13. c[i] += k;
    14. }
    15. }
    16. int getSum(int x){//得知比x小的数字的个数
    17. int sum = 0;
    18. for(int i=x;i>0;i-=lowbit(i)){
    19. sum+=c[i];
    20. }
    21. return sum;
    22. }
    23. int main(){
    24. int n;
    25. scanf("%d",&n);
    26. for(int i=0;i
    27. string a;
    28. a.resize(20);
    29. int t;
    30. scanf("%s",&a[0]);
    31. if(a[1] == 'o'){
    32. if(r.empty()) printf("Invalid\n");
    33. else{
    34. update(r.top(),-1);
    35. printf("%d\n",r.top());
    36. r.pop();
    37. }
    38. }else if(a[1] == 'u'){
    39. scanf("%d",&t);
    40. r.push(t);
    41. update(t,1);
    42. }else{
    43. if(r.empty()) printf("Invalid\n");
    44. else{
    45. int left = 1,right = max,mid,k = (r.size()+1)/2;
    46. while(left
    47. mid = (right+left)/2;
    48. if(getSum(mid)>=k){
    49. //一定是找到等于k的最小的下标
    50. right = mid;
    51. }else{
    52. left = mid+1;
    53. }
    54. }
    55. printf("%d\n",left);
    56. }
    57. }
    58. }
    59. return 0;
    60. }

  • 相关阅读:
    为什么文件进行压缩后总是自带密码?
    模拟电路 第二章(三极管及其放大电路)【上】
    GIS与人工智能应用结合举例
    CDA数据分析——AARRR增长模型的介绍、使用
    《量子计算:下一个大风口,还是一个热炒概念?》
    Atlassian confluence迁移数据库步骤
    Jmeter性能测试步骤
    C语言-写一个简单的Web服务器(三)
    docker提交镜像到阿里ack整体流程
    阿里云的redis集群操作
  • 原文地址:https://blog.csdn.net/weixin_55202895/article/details/126706201