• 【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. }

  • 相关阅读:
    SpringBoot系列之集成Redission入门与实践教程
    直播倒计时 1 天|SOFAChannel#35《SOFABoot 4.0 — 迈向 JDK 17 新时代》
    前端实现SuperMap iServer服务增(发布)删改查和刷新的方法.md
    git 本地多个账号错乱问题解决
    C语言实现计算机网络技术
    初见物理引擎库Cannon.js:与Cesium的整合
    从语言层面了解线程(std::thread)使用的里里外外
    超标量处理器设计 姚永斌 第6章 指令解码 摘录
    秋招—文思海辉笔试题
    字符串 --- 不可变性与驻留池
  • 原文地址:https://blog.csdn.net/weixin_55202895/article/details/126706201