zoukankan      html  css  js  c++  java
  • PAT 1057 Stack [难][树状数组]

    1057 Stack (30)(30 分)

    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

     题目大意:栈原本有push和pop的操作,现在加入了PeekMedian 即输出中值元素的操作,输入命令,输出相应的结果。

     //关键就是怎么求中值不会导致超时。

    //其实就是实现一种数据结构,能够查询头,弹出头,求中值。

     代码来自:https://www.liuchuo.net/archives/2265

    #include <iostream>
    #include <stack>
    #define lowbit(i) ((i) & (-i))
    const int maxn = 100010;
    using namespace std;
    int c[maxn];//这个是用来计数每个元素出现的次数,比如push 3,那么就是3多了一个。
    //表示≤当前下标的有几个。
    stack<int> s;
    void update(int x, int v) {
        for(int i = x; i < maxn; i += lowbit(i))//更新这么多的吗?
            c[i] += v;
    }
    int getsum(int x) {
        int sum = 0;
        for(int i = x; i >= 1; i -= lowbit(i))
            sum += c[i];
        return sum;
    }
    void PeekMedian() {
        int left = 1, right = maxn, mid, k = (s.size() + 1) / 2;
        while(left < right) {//使用二分法查找。
            mid = (left + right) / 2;
            if(getsum(mid) >= k)
                right = mid;
            else
                left = mid + 1;
        }
        printf("%d\n", left);
    }
    int main() {
        int n, temp;
        scanf("%d", &n);
        char str[15];
        for(int i = 0; i < n; i++) {
            scanf("%s", str);
            if(str[1] == 'u') {//这样判断比较快
                scanf("%d", &temp);
                s.push(temp);
                update(temp, 1);//更新
            } else if(str[1] == 'o') {
                if(!s.empty()) {
                    update(s.top(), -1);
                    printf("%d\n", s.top());
                    s.pop();
                } else {
                    printf("Invalid\n");
                }
            } else {
                if(!s.empty())
                    PeekMedian();
                else
                    printf("Invalid\n");
            }
        }
        return 0;
    }

    //这真的相当厉害,叹为观止。太厉害了。

    1.取中值并没有采取对数据进行排序的思想,而是使用树状数组存储下标,下标就是数据的值。c[i]便表示≤当前值的数的个数。

    2.当push时对其进行更新,更新的参数为1,即当前数+1.为了getSum函数,所以对其他包含当前的数也进行更新。

    3.当pop时操作的是栈顶的元素,更新的参数为-1。

  • 相关阅读:
    传的参数乱码
    Tp5.0中分页加搜索的用法!!!
    TP5.0循环更新数据问题
    TP5.0中foreach里面使用save方法变成更新问题
    TP5.0中软删除的用法
    TP5.0中save方法加主键id的用法!!!
    用宝塔的定时任务写shell命令会以root执行的解决方法
    兆易创新RISC-V开发板评测
    使用vsCode配合IAR搭建arm开发环境
    Vue 路由导航解析流程
  • 原文地址:https://www.cnblogs.com/BlueBlueSea/p/9518202.html
Copyright © 2011-2022 走看看