PAT A1057

疑问

暂无

代码

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

反思

  1. 由于本题中N≤100000,所以不能直接用暴力的方法解题(肯定会超时的),应该使用分块的思想,复杂度为 O ( N N ) O(N\sqrt{N}) O(NN )
  2. 参考《算法笔记》上的解答,发现这里的栈stack可以直接使用C++ STL中的stack<int>
  3. 对于字符串输入pop key的处理,我使用的是sscanf,与《算法笔记》上有所不同;
  4. 再说peekMedian()的处理,应该先直接把K确定,然后直接求第K个就好了,不要再分奇偶,我的代码过于繁琐了。。。
  5. strcmp()可以直接比较字符串如strcmp(command,"Pop")
  6. 总的来说,纸上得来终觉浅,绝知此事要躬行,我看书看得懂,但是实际操作起来很生疏,practice makes perfect.
  7. 要注意pushpop操作是互逆的,之前一直过不了是因为pop里的很多操作漏掉了。
  8. 另一种解法是使用树状数组:
#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;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值