【题意】
在一般的栈的基础上,增加一个取中位数的功能
【思路】
1. 采用树状数组记录数字出现次数的部分和
2. 用两个集合(要用multiset)存储高低两部分的数,在Push和Pop后保证高部分的set至少比低部分的多1个,至多多2个(除非都是空的),这样取高部分的第一个数即是中位数了
3. 我本来的思路是用一个vector模拟栈,然后在要取中位数时排序并输出,但这样会在三个点超时。另外我也试过直接用stack,并用一个multiset存数字,但这样无法在O(1)时间内找到中位数(set不支持随机取数),依然会超时
【注意点】
无论用何种方法,都需要scanf读和printf写,否则会超时
用树状数组解:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <stack>
using namespace std;
#define MAXKEY 100000
int c[MAXKEY+1];
int lowbit(int x){
return x&(-x);
}
void add(int index, int num){
while(index<=MAXKEY){
c[index] += num;
index += lowbit(index);
}
}
int sum(int index){
int res = 0;
while(index){
res += c[index];
index -= lowbit(index);
}
return res;
}
int findIndex(int n){
int left,right,mid;
left = 1;
right = MAXKEY;
while(left<right){
mid = (left+right)/2;
if(sum(mid)<n){
left = mid+1;
}
else{
right = mid;
}
}
return left;
}
int main(int argc, char const *argv[])
{
stack<int> ss;
int n;
memset(c,0,sizeof(c));
scanf("%d", &n);
while(n--){
char command[11];
scanf("%s", command);
if(strcmp(command,"Push")==0){
int num;
scanf("%d", &num);
add(num,1);
ss.push(num);
}
else if(strcmp(command,"Pop")==0){
if(ss.empty()){
printf("Invalid\n");
}
else{
printf("%d\n", ss.top());
add(ss.top(),-1);
ss.pop();
}
}
else{
if(ss.empty()){
printf("Invalid\n");
}
else{
printf("%d\n", findIndex((ss.size()+1)/2));\
}
}
}
system("pause");
return 0;
}
用两个multiset快速找到中位数:
#include <iostream>
#include <stack>
#include <set>
#include <functional>
#include <cstdio>
#include <cstring>
using namespace std;
int main(int argc, char const *argv[])
{
stack<int> st;
multiset<int> upper;
multiset<int,greater<int>> lowwer;
int n;
scanf("%d", &n);
while(n--){
char command[11];
int num;
scanf("%s", command);
if(strcmp(command,"Pop")==0){
if(st.empty()){
printf("Invalid\n");
}
else{
printf("%d\n", st.top());
if(*upper.begin()<=st.top()){
upper.erase(upper.find(st.top()));
}
else{
lowwer.erase(lowwer.find(st.top()));
}
st.pop();
if(upper.size()==lowwer.size() && lowwer.size()>0){
upper.insert(*(lowwer.begin()));
lowwer.erase(lowwer.begin());
}
else if(upper.size()-lowwer.size()>2){
lowwer.insert(*upper.begin());
upper.erase(upper.begin());
}
}
}
else if(strcmp(command,"Push")==0){
scanf("%d", &num);
st.push(num);
if(lowwer.size()>0 && *lowwer.begin()>st.top()){
lowwer.insert(st.top());
}
else{
upper.insert(st.top());
}
if(upper.size()==lowwer.size()){
upper.insert(*(lowwer.begin()));
lowwer.erase(lowwer.begin());
}
else if(upper.size()-lowwer.size()>2){
lowwer.insert(*upper.begin());
upper.erase(upper.begin());
}
}
else{
if(st.empty()){
printf("Invalid\n");
}
else{
printf("%d\n", *upper.begin());
}
}
}
system("pause");
return 0;
}