1. 程式人生 > 實用技巧 >pat_棧(二分+棧模擬)

pat_棧(二分+棧模擬)

現在,你需要實現一個棧,該棧要具有一個額外的操作:PeekMedian-返回棧中所有元素的中值。
對於 N 個元素,如果 N 為偶數,則中值定義從小到大第 N2 個元素;如果 N 為奇數,則中值定義為從小到大第 N+12 個元素。
輸入格式
第一行包含整數 N,表示命令數。
接下來 N 行,每行包含以下三種命令中的一種:
Push key
Pop
PeekMedian
其中 key 是一個不超過 105 的正整數。
輸出格式
對於每個 Push 操作,在頂部插入一個 key 值,不輸出任何內容。
對於每個 Pop 或 PeekMedian 命令,在一行中輸出相應的返回值。
如果命令無效,則輸出 Invalid。
資料範圍


1≤N≤105

方法一:2*multiset+stack模擬

這題有毒,用cin不能做,

#include<bits/stdc++.h>
using namespace std;
int mid;
multiset<int> s1, s2;
string s;
void update() {
    multiset<int>:: iterator it;
    if (s1.size()<s2.size()) {
        it=s2.begin(); 
        s1.insert(*it), s2.erase(it);
    }if (s1.size()>s2.size()+1) {
        it=s1.end(); it--;
        s2.insert(*it), s1.erase(it);
    }if (!s1.empty()) {
        it=s1.end(); it--;
        mid=*it;
    }
}
int main() {
    int n; scanf("%d",&n);
    stack<int> st;
    
    for (int i=0; i<n; i++) {
        cin>>s;
        if (s=="Pop") {
            if (st.empty()) cout << "Invalid" << '\n';
            else {
                int t=st.top(); st.pop();
                printf("%d\n", t);
                if (t>mid) s2.erase(s2.find(t));
                else       s1.erase(s1.find(t));
                update();
            }
        } else if (s=="Push") {
            getchar(); int e; scanf("%d",&e);
            st.push(e);
            if (s1.empty()||e<=mid) s1.insert(e);
            else s2.insert(e);
            update();
        } else {
            if (st.empty()) printf("Invalid\n");
            else printf("%d\n",mid);
        }
    }
    return 0;
}

複雜度分析

  • Time\(O(nlogn)\)
  • Space\(O(n)\)