Input Specification:
Push key Pop PeekMedian
key
1.
Output Specification:
Push
key
Pop
PeekMedian
Invalid
Sample Input:
17 Pop PeekMedian Push 3 PeekMedian Push 2 PeekMedian Push 1 PeekMedian Pop Pop Push 5 Push 4 PeekMedian Pop Pop Pop Pop
Sample Output:
Invalid Invalid 3 2 2 1 2 4 4 5 3 Invalid
由于N<=10^5,暴力算法肯定超时,我一开始思考用multiset容器可以自动排序,只要找到中值即可
#include<cstdio> #include<set> #include<cstring> #include<stack> using namespace std; stack<int> st; multiset<int> se; int tot=0; int main(){ int n,m; char s[20]; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",s); if(strcmp(s,"Pop")==0){ if(tot==0) printf("Invalid\n"); else{ int x=st.top(); st.pop(); se.erase(x); tot--; printf("%d\n",x); } }else if(strcmp(s,"Push")==0){ scanf("%d",&m); st.push(m); se.insert(m); tot++; }else{ if(tot==0) printf("Invalid\n"); else{ int k=tot; if(k%2==1) k=(k+1)/2; else k=k/2; multiset<int>::iterator it=se.begin(); for(int i=1;i<=k-1;i++) it++; int x=*it; printf("%d\n",x); } } } return 0; }

set容器不能直接访问中值,这是由于底层是平衡树的原因,看来实际效果不好,学习了书上的分块思想,复杂度可达O(N√N)
#include<cstdio> #include<cstring> #include<stack> using namespace std; const int maxn=100010; const int sqrN=316; stack<int> st; int block[sqrN]; int hash[maxn]; void Push(int x){ st.push(x); hash[x]++; int c=x/sqrN; block[c]++; } void Pop(){ int x=st.top(); printf("%d\n",x); st.pop(); block[x/sqrN]--; hash[x]--; } void peekMedian(int k){//第k小 int sum=0; int idx=0; while(sum+block[idx]<k) sum+=block[idx++]; int num=idx*sqrN; while(sum+hash[num]<k) sum+=hash[num++]; printf("%d\n",num); } int main(){ int n,m; char s[20]; scanf("%d",&n); memset(block,0,sizeof(block)); memset(hash,0,sizeof(hash)); for(int i=1;i<=n;i++){ scanf("%s",s); if(strcmp(s,"Pop")==0){ if(st.size()==0) printf("Invalid\n"); else Pop(); }else if(strcmp(s,"Push")==0){ scanf("%d",&m); Push(m); }else{ if(st.size()==0) printf("Invalid\n"); else{ int k=st.size(); if(k%2==1) k=(k+1)/2; else k=k/2; peekMedian(k); } } } return 0; }