pat甲级1057 Stack (30 分)

欢迎访问我的pat甲级题解目录

题目描述

pat甲级1057 Stack (30 分)题目描述

算法设计

由于栈内数据随时变化,还要随时查找中位数,我们可以额外建立一个树状数组来求中位数。由于n不会超过 1 0 5 10^5 ,因此我们可以开辟一个长 1 0 5 + 5 10^5+5 的树状数组c。设计getSum(x)函数表示1到x这些数字在序列中出现次数之和。设计update函数用于更新数字出现次数。
每次压栈,都将树状数组对应数字出现次数加1;每次出栈,都将树状数组对应数字出现次数减1。查找中位数时,随着x的增长,getSum(x)也是递增的,所以我们可以采取二分查找的方式找到第一个使得 g e t S u m ( x ) > = / 2 getSum(x)>=栈内数据个数/2 的x,即为中位数。

C++代码

#include <bits/stdc++.h>
using namespace std;
auto lowbit = [](int x) { return x & (-x); };
vector<int> c(100005);
void update(int x, int v) {
    for (int i = x; i < c.size(); i += lowbit(i))
        c[i] += v;
}
int getSum(int x) {
    int sum = 0;
    for (int i = x; i > 0; i -= lowbit(i))
        sum += c[i];
    return sum;
}
int search(int left, int right, int k) {
    int mid;
    while (left <= right) {
        if (left == right)
            return getSum(left) >= k ? left : left + 1;
        mid = left + (right - left) / 2;
        if (getSum(mid) >= k)
            right = mid;
        else
            left = mid + 1;
    }
    return left;
}
int main() {
    int n, a;
    stack<int> s;
    string command;
    cin >> n;
    while (cin >> command) {
        if (command == "Push") {
            cin >> a;
            s.push(a);
            update(a, 1);
        } else if (s.empty()) {
            cout << "Invalid\n";
        } else if (command == "Pop") {
            cout << s.top() << "\n";
            update(s.top(), -1);
            s.pop();
        } else if (command == "PeekMedian") {
            cout << search(1, c.size() - 1, (s.size() + 1) / 2) << "\n";
        }
    }
    return 0;
}
发布了528 篇原创文章 · 获赞 1015 · 访问量 37万+

猜你喜欢

转载自blog.csdn.net/richenyunqi/article/details/102733886