1057 Stack (分块思想)

匿名 (未验证) 提交于 2019-12-02 23:05:13

Input Specification:

Push key Pop PeekMedian 

key1.

Output Specification:

PushkeyPopPeekMedianInvalid

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!