疑问
暂无
代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
using namespace std;
//使用两个不同的数组来分别进行操作,一个用于入栈出栈,一个用于排序
const int size = sqrt(100000.0);
const int number = sqrt(100000.0)+1;
const int maxn = 100010;
//block代表分组,block[i]表示第i组有多少个值
int block[number] = {0};
//stack代表栈
int stack[maxn] = {0};
//table代表映射
int table[maxn]={0};
//len表示stack的有效长度
int len=0;
char popStr[20]="Pop";
char peek[20]="PeekMedian";
void pop(){
table[stack[len-1]]--;
block[stack[len-1]/size]--;
printf("%d\n",stack[len-1]);
len--;
}
void peekMedian(){
//n表示序号
int n=0;
//i表示block下标
int i=0;
if(len%2==0){
//偶数
while(n < len/2){
n += block[i];
i++;
}
n -= block[i-1];
for(int j=(i-1)*size;;j++){
n+=table[j];
if(n >= len/2){
printf("%d\n",j);
break;
}
}
}else{
//奇数
while(n < ((len+1)/2)){
n += block[i];
i++;
}
n -= block[i-1];
for(int j=(i-1)*size;;j++){
n+=table[j];
if(n >= ((len+1)/2)){
printf("%d\n",j);
break;
}
}
}
}
void push(int n){
stack[len] = n;
len++;
table[n]++;
block[n/size]++;
}
void operate(char command[]){
if(!strcmp(command,popStr)){
if(len==0){
printf("Invalid\n");
}else{
pop();
}
}else if(!strcmp(command,peek)){
if(len==0){
printf("Invalid\n");
}else{
peekMedian();
}
}else{
int n;
sscanf(command+5,"%d",&n);
push(n);
}
}
int main(){
int N;
scanf("%d\n",&N);
for(int i=0;i<N;++i){
char command[20];
cin.getline(command,20);
operate(command);
}
return 0;
}
反思
- 由于本题中
N≤100000
,所以不能直接用暴力的方法解题(肯定会超时的),应该使用分块的思想,复杂度为 O ( N N ) O(N\sqrt{N}) O(NN); - 参考《算法笔记》上的解答,发现这里的栈stack可以直接使用C++ STL中的
stack<int>
; - 对于字符串输入
pop key
的处理,我使用的是sscanf
,与《算法笔记》上有所不同; - 再说
peekMedian()
的处理,应该先直接把K
确定,然后直接求第K
个就好了,不要再分奇偶,我的代码过于繁琐了。。。 strcmp()
可以直接比较字符串如strcmp(command,"Pop")
;- 总的来说,纸上得来终觉浅,绝知此事要躬行,我看书看得懂,但是实际操作起来很生疏,practice makes perfect.
- 要注意
push
和pop
操作是互逆的,之前一直过不了是因为pop
里的很多操作漏掉了。 - 另一种解法是使用树状数组:
#include<cstdio>
#include<cstring>
#include<stack>
#include<iostream>
#define lowbit(i) ((i)&(-i))
using namespace std;
const int maxn = 100010;
//栈
stack<int> s;
//c数组
int c[maxn]={0};
//总的操作数
int n;
//操作命令
char cmd[20];
void update(int x,int v){
for(int i = x;i < maxn;i += lowbit(i)){
c[i] += v;
}
}
int getSum(int x){
int sum = 0;
for(int i=x;i>0;i-=lowbit(i)){
sum += c[i];
}
return sum;
}
void findKthElement(int K){
int l = 1;
int r = maxn;
int mid;
while(l < r){
mid = (l + r) / 2;
if(getSum(mid) >= K){
r = mid;
}else{
l = mid + 1;
}
}
printf("%d\n",l);
}
void Pop(){
int x = s.top();
s.pop();
update(x,-1);
printf("%d\n",x);
}
void Push(int x){
s.push(x);
update(x,1);
}
void PeekMedian(){
int len = s.size();
int K = (len+1) / 2;
findKthElement(K);
}
void operate(char cmd[]){
if(!strcmp(cmd,"Pop")){
if(s.empty()){
printf("Invalid\n");
}else{
Pop();
}
}else if(!strcmp(cmd,"PeekMedian")){
if(s.empty()){
printf("Invalid\n");
}else{
PeekMedian();
}
}else{
int x;
sscanf(cmd+5,"%d",&x);
Push(x);
}
}
int main(){
scanf("%d",&n);
getchar();
for(int i=0;i<n;++i){
cin.getline(cmd,20);
operate(cmd);
}
return 0;
}