【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;
}
}
}

浙公网安备 33010602011771号