自己写的代码测试点2、3、4一直超时,参考了别人的代码发现要用树状数组(学到了
代码参考:1057. Stack (30)-PAT甲级真题(树状数组)_柳婼 の blog-CSDN博客_pat甲级柳
树状数组学习参考:树状数组 数据结构详解与模板(可能是最详细的了)_bestsort-CSDN博客_树状数组
树状数组简单易懂的详解_FlushHip-CSDN博客_树状数组
如果下限定为0的话,同样的代码报错,定为1就不报错了,原因还要思考思考(估计和树状数组特性有关
PS:想明白了,如果for循环头部这样写:for(int i=index;i>=0;i-=lowbit(i)),当i变为0时,lowbit的值恒为0,循环就跳不出了,是个要注意的小细节
姑且是这题通过了,但是原理还是有点不明白,还要研究亿下
#include<iostream>
#include<stack>
using namespace std;
#define lowbit(i) ((i)&(-i))
stack<int>s;
int c[100001] = { 0 };
void pop() {
if (s.size() == 0) {
printf( "Invalid\n");
return;
}
int t = s.top();
s.pop();
for (int i = t; i <= 100000; i += lowbit(i))
c[i]--;
printf("%d\n",t);
return;
}
int sum(int index) {
int s = 0;
for (int i = index; i >= 1; i -= lowbit(i))
s += c[i];
return s;
}
void peekMedian() {
if (s.size() == 0) {
printf("Invalid\n");
return;
}
int size = s.size();
int pos = (size % 2 == 0) ? size / 2 : (size + 1) / 2;
int left = 1; int right =100000;
while (left < right) {
int mid = (left + right) / 2;
if (sum(mid) >= pos)
right = mid;
else
left = mid + 1;
}
printf("%d\n", left);
}
int main() {
int N; scanf("%d",&N);
for (int i = 1; i <= N; i++) {
char command[10];
scanf("%s",&command);
if (command[1]=='o')
pop();
else if (command[1]=='e')
peekMedian();
else {
int p; scanf("%d",&p);
s.push(p);
for (int i = p; i <= 100000; i += lowbit(i))
c[i]++;
}
}
return 0;
}