PAT(上級レベル)実践1057スタック(30ポイント)フェンウィックツリー]

スタックは最終でファーストアウト(LIFO)の原理に基づいている最も基本的なデータ構造の一つです。基本的な操作は、プッシュ(上部の位置に要素を挿入する)およびポップ(トップ要素を削除する)が挙げられます。今、あなたは余分な操作でスタックを実装することになっている:PeekMedian - スタック内のすべての要素の中央値を返します。とともに N N 要素は、中央値であると定義されます ( N / 2 ) (N / 2) であれば番目の最小の要素 N N 偶数ですか、 ( ( N + 1 ) / 2 ) ((N + 1)/ 2) 番目の場合 N N 奇数です。

入力仕様:

各入力ファイルには、1つのテストケースが含まれています。各場合について、最初の行は、正の整数を含んでいます N ( 1 0 5 ) N(≤10^ 5) それから N N 行はそれぞれが以下の3つのいずれかの形式でコマンドを含む、次のとおりです。

Push key
Pop
PeekMedian

どこkey正の整数がせいぜいではありません 1 0 5 10 ^ 5

出力仕様:

それぞれについてPush、コマンド、挿入keyスタックおよび出力何に。Pop又はPeekMedianコマンドラインに対応する戻り値を出力。コマンドが無効である場合は、印刷Invalidの代わりに。

サンプル入力:

17
Pop
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
Pop
Push 5
Push 4
PeekMedian
Pop
Pop
Pop
Pop

サンプル出力:

Invalid
Invalid
3
2
2
1
2
4
4
5
3
Invalid

問題の意味

スタックを実装するには、スタックは、出力関数値を持っています。

思考

フェンウィックツリー。

コード

#include <cstdio>
#include <cstring>
#include <stack>

using namespace std;

#define lowbit(i) ((i) & -(i)) // xxx100...

const int MAX_N = 100010;
stack<int> s;
int c[MAX_N]; // 树状数组

void update(int x, int v) { // 更新操作,将位置x的元素加上v
    for (int i = x; i < MAX_N; i += lowbit(i))
        c[i] += v; // 依次向上更新
}

int getSum(int x) { // 求和操作,返回位置1~x的元素之和
    int sum = 0;
    for (int i = x; i > 0; i -= lowbit(i))
        sum += c[i];
    return sum;
}

void peekMedia() { // 二分法求第K大
    int l = 1, r = MAX_N, mid, k = (s.size() + 1) / 2;
    while (l < r) {
        mid = (l + r) / 2;
        if (getSum(mid) >= k)
            r = mid;
        else
            l = mid + 1;
    }
    printf("%d\n", l);
}

int main() {
    int n, x;
    char str[12];
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
        scanf("%s", str);
        if (strcmp(str, "Push") == 0) {
            scanf("%d", &x);
            s.push(x);    // 入栈
            update(x, 1); // 将位置x加1
        } else if (strcmp(str, "Pop") == 0) {
            if (s.empty())
                printf("Invalid\n");
            else {
                printf("%d\n", s.top());
                update(s.top(), -1); // 将栈顶元素所在位置减1
                s.pop();             // 出栈
            }
        } else if (strcmp(str, "PeekMedian") == 0) {
            if (s.empty())
                printf("Invalid\n");
            else
                peekMedia();
        }
    }
}
发布了184 篇原创文章 · 获赞 19 · 访问量 2万+

おすすめ

転載: blog.csdn.net/Exupery_/article/details/104158745