• 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。

  • 相关阅读:
    表单上传,接收非文件参数
    CompletableFuture 获取所有task的结果
    CNVD-2021-30167:用友NC BeanShell远程代码执行漏洞复现
    restful接口优化
    中科院院士:初等数学和高等数学,总结起来就这几点<转载>
    Vue打包报错Unexpected token: punc(()解决方案
    Echarts表格三连的效果
    React 项目 或者 Vue项目 中引用 第三方插件的时候,如果不在npm库上,则需把静态文件放入项目进行引用
    ios touch事件 获取 event的 clientX/Y
    GCC | GCC编译器
  • 原文地址:https://www.cnblogs.com/BlueBlueSea/p/9518202.html
Copyright © 2020-2023  润新知