PAT-1057 Stack (树状数组 + 二分查找)
1057. Stack
Stack is one of the most fundamental data structures, which is based on the principle of Last In First Out (LIFO). The basic operations include Push (inserting an element onto the top position) and Pop (deleting the top element).
Now you are supposed to implement a stack with an extra operation: PeekMedian -- return the median value of all the elements in the stack. With N elements, the median value is defined to be the (N/2)-th smallest element if N is even, or ((N+1)/2)-th if N is
odd.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (<= 105). Then N lines follow, each contains a command in one of the following 3 formats:
Push key
Pop
PeekMedian
where key is a positive integer no more than 105.
Output Specification:
For each Push command, insert key into the stack and output nothing. For each Pop or PeekMedian command, print in a line the corresponding returned value. If the command is invalid, print "Invalid" instead.
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
题目大意:要求实现一个栈,除了基础的push和pop操作外,还要拥有查找中间数的操作
(PeekMedian),即n个栈中元素在排序后,该元素的大小排行为 (n+1)/2。因为可能存在大量的查找中间数的操作,所以必须找到快速的解决方法。
主要思想:解此题的过程可谓是一波三折。开始的想法很天真,在每次需要PeekMedian的时候,将栈中元素全部拷贝到一个辅助数组,然后对该数组进行排序,很容易找到中间值,时间复杂度为
O((n^2) lgn),很显然最后超时了。
由于题目说明数据范围为 1~100000,想到了用一个count[]数组来储存每一个数在栈中的个数,然后每一次通过遍历数组累积,当 S[i] = count[1] + count[2] + ... + count[i] >= (n+1)/2 的时候则找到中间值i,时间复杂度为 O(n^2)。
这样显然还会超时,在这个想法的基础上利用树状数组,这种数据结构可以很快的得出前 i 项和,从而可以利用二分查找来找到中间数。于是,push和pop操作时间复杂度为 O(lgn),PeekMedian的复杂度为 O(n (lgn)^2),问题解决。
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string.h>
#define MAXN 100005
using namespace std;
int stack[MAXN]; //array of stack
int c[MAXN]; //BIT
int n = 0;
/*
functions of Binary Index Tree (BIT)
*/
int lowbit(int x) {
return x & (-x);
}
int get_sum(int x) {
int sum = 0;
for (int i = x; i > 0; i -= lowbit(i))
sum += c[i];
return sum;
}
void update(int x, int t) {
for (int i = x; i <= MAXN; i += lowbit(i))
c[i] += t;
} /*
operations of stack
*/
bool isEmpty() {
return n == 0;
}
void push(int key) {
stack[n++] = key;
update(key, 1);
}
int pop() {
int k = stack[--n];
update(k, -1);
return k;
}
int peek_median() {
int lo = 1, hi = MAXN;
int median = (n + 1) / 2; //use the binary search
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (median > get_sum(mid))
lo = mid + 1;
else // median <= get_sum(mid)
hi = mid - 1;
}
return lo;
} int main(void) {
int m;
char comment[11]; scanf("%d", &m);
getchar();
for (int i = 0; i < m; i++) {
gets(comment);
if (comment[1] == 'u') { //push
int key = atoi(comment+5);
push(key);
}
else if (comment[1] == 'o') { //pop
if(isEmpty()) {
printf("Invalid\n");
continue;
}
int t = pop();
printf("%d\n", t);
}
else { //peek median
if (isEmpty()) {
printf("Invalid\n");
continue;
}
int m = peek_median();
printf("%d\n", m);
}
} return 0;
}
PAT-1057 Stack (树状数组 + 二分查找)的更多相关文章
- 1057 Stack 树状数组
Stack is one of the most fundamental data structures, which is based on the principle of Last In Fir ...
- POJ 2182 Lost Cows (树状数组 && 二分查找)
题意:给出数n, 代表有多少头牛, 这些牛的编号为1~n, 再给出含有n-1个数的序列, 每个序列的数 ai 代表前面还有多少头比 ai 编号要小的牛, 叫你根据上述信息还原出原始的牛的编号序列 分析 ...
- toj 4353 Estimation(树状数组+二分查找)
Estimation 时间限制(普通/Java):5000MS/15000MS 运行内存限制:65536KByte总提交: 6 测试通过: 1 描述 “There are ...
- 树状数组+二分||线段树 HDOJ 5493 Queue
题目传送门 题意:已知每个人的独一无二的身高以及排在他前面或者后面比他高的人数,问身高字典序最小的排法 分析:首先对身高从矮到高排序,那么可以知道每个人有多少人的身高比他高,那么取较小值(k[i], ...
- poj2182Lost Cows——树状数组快速查找
题目:http://poj.org/problem?id=2182 从后往前确定,自己位置之前没有被确定的且比自己编号小的个数+1即为自己的编号: 利用树状数组快速查找,可另外开一个b数组,角标为编号 ...
- P2161 [SHOI2009]会场预约[线段树/树状数组+二分/STL]
题目描述 PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地.这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突.也就是说,前一个 ...
- 牛客多校第3场 J 思维+树状数组+二分
牛客多校第3场 J 思维+树状数组+二分 传送门:https://ac.nowcoder.com/acm/contest/883/J 题意: 给你q个询问,和一个队列容量f 询问有两种操作: 0.访问 ...
- POJ 2828 Buy Tickets (线段树 or 树状数组+二分)
题目链接:http://poj.org/problem?id=2828 题意就是给你n个人,然后每个人按顺序插队,问你最终的顺序是怎么样的. 反过来做就很容易了,从最后一个人开始推,最后一个人位置很容 ...
- TZOJ 4602 高桥和低桥(二分或树状数组+二分)
描述 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低桥之上,所以不算“淹了两次”.举 ...
随机推荐
- 运用jieba库统计词频及制作词云
一.对中国十九大报告做词频分析 import jieba txt = open("中国十九大报告.txt.txt","r",encoding="utf ...
- yum报[Errno 256] No more mirrors to try
解决方法: yum clean all #清除yum缓存yum makecache #将服务器软件包写到本地缓存,提高包的搜索.安装效率
- 使用 html5 FileReader 获取图片, 并异步上传到服务器 (不使用 iframe)
为什么80%的码农都做不了架构师?>>> 原理: 1.使用FileReader 读取图片的base64编码 2.使用ajax,把图片的base64编码post到服务器. 3.根据 ...
- 【K8S】K8S部署Metrics-Server服务
写在前面 在新版的K8S中,系统资源的采集均使用Metrics-Server服务,可以通过Metrics-Server服务采集节点和Pod的内存.磁盘.CPU和网络的使用率等信息. 读者可参考< ...
- C语言编程入门题目--No.11
题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月 后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析: 兔子的规律为数列1,1,2,3, ...
- 背英语单词很困难,不妨学习一下词根词缀吧(每天10个词根、词缀)Part 3
1.ir- 不,向内 例词: irregular=ir(不)-regular(规则的)=不规则的 irrigate=ir(向内)-rigate(浇水)=灌溉 2. kilo- 千 例词: kilogr ...
- 地表最强的MySQL安装一键式安装,信不信你下完我就给你装好!附各种Mysql安装失败的解决办法(什么你安装失败了?快来看这个)
这里还有数据库相关的优质文章:快戳我,快戳我
- CodeForces - 1245F Daniel and Spring Cleaning (数位DP)
While doing some spring cleaning, Daniel found an old calculator that he loves so much. However, it ...
- celery的定时任务
定时任务 Celery 中启动定时任务有两种方式,(1)在配置文件中指定:(2)在程序中指定. # cele.py import celery app = celery.Celery('cele', ...
- java反编译软件
1.Java反编译插件 —— Jadclipse JadClipse是Jad的Eclipse插件,是一款非常实用而且方便地Java反编译插件,我们只需将下载的插件包复制到eclipse的plugins ...