【1057 30 权值树状数组】 Stack

传送门

题意

给定 \(n\) 个操作,操作一共有 \(3\) 种,如下

  • \(Push,Key\),将 \(Key\) 压入栈,无输出
  • \(Pop\),移除栈顶并输出移除的元素,如果栈空输出 \(Invalid\)
  • \(PeekMedian\),输出栈中元素的中位数,如果栈空输出 \(Invalid\)

数据范围

$K\leq 10^{5} $

题解

  • 模拟栈,通过判断栈中是否有元素来输出
  • 中位数的查找通过权值树状数组,树状数组中统计的是权值范围内每个数的个数
  • 在权值范围二分找到数量前缀和为中位数位置的数字

Code

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int c[N],stk[N],n,tp;
int lowbit(int x){ return x&-x; }
void add(int id,int x){
    for(int i=id;i<=N;i+=lowbit(i)){
        c[i]+=x;
    }
}
int query(int id){
    int res=0;
    for(int i=id; i; i-=lowbit(i)){
        res+=c[i];
    }
    return res;
}
int main(){
    int n; cin>>n;
    while(n--){
        string cmd; cin>>cmd;
        if(cmd=="Pop"){
            if(tp) {
                cout<<stk[tp]<<endl;
                add(stk[tp],-1);
                tp--;
            } else cout<<"Invalid"<<endl;
        } else if(cmd=="Push"){
            int x; cin>>x;
            stk[++tp]=x;
            add(x,1);
        } else {
            if(tp){
                int idx=(tp+1)>>1;
                int l=1,r=N;
                while(l<r){
                    int mid=l+r>>1;
                    if(query(mid)>=idx) r=mid;
                    else l=mid+1;
                }
                cout<<l<<endl;
            } else cout<<"Invalid"<<endl;
        }
    }
}
posted @ 2021-02-25 13:28  Hyx'  阅读(96)  评论(0)    收藏  举报