【栈】日志分析(BSOJ2981)
Description
M海运公司最近要对旗下仓库的货物进出情况进行统计。目前他们所拥有的唯一记录就是一个记录集装箱进出情况的日志。该日志记录了两类操作:第一类操作为集装箱入库操作,以及该次入库的集装箱重量;第二类操作为集装箱的出库操作。这些记录都严格按时间顺序排列。集装箱入库和出库的规则为先进后出,即每次出库操作出库的集装箱为当前在仓库里所有集装箱中最晚入库的集装箱。
出于分析目的,分析人员在日志中随机插入了若干第三类操作——查询操作。分析日志时,每遇到一次查询操作,都要报告出当前仓库中最大集装箱的重量。
Input
包含N+1 行:
第一行为1 个正整数N,对应于日志内所含操作的总数。
接下来的N 行,分别属于以下三种格式之一:
格式1: 0 X //一次集装箱入库操作,正整数X表示该次入库的集装箱的重量 格式2: 1 //一次集装箱出库操作,(就当时而言)最后入库的集装箱出库
格式3: 2 //一次查询操作,要求分析程序输出当前仓库内最大集装箱的重量 当仓库为空时你应该忽略出库操作,当仓库为空查询时你应该输出0。
Output
输出行数等于日志中查询操作的次数。每行为一个正整数,表示查询结果。
Sample Input
13
0 1
0 2
2
0 4
0 2
2
1
2
1
1
2
1
2
Sample Output
2
4
4
1
0
Hint
【数据规模】
对于20%的数据,有N≤10;
对于40%的数据,有N≤1000;
对于100%的数据,有N≤200000,X≤10^8。
Thinking
就从简单题开始吧。首先这是一道非常裸的栈的题目,入栈出栈操作都有,关键是处理询问。
因为需要维护最大值,很容易想到用优先队列或是堆这样的方法,但是他们的共同问题就是删除操作不好处理。考虑到栈里的元素,先进栈的一定后出,所以在入栈时最大值具有单调性。所以理论上是有O(n)复杂度的算法的,用堆大材小用了。
于是我们改变思路,用栈保存到当前元素为止的最大值。对于每次入栈的元素x,判断x与当前栈顶的大小关系。如果x较大则x入栈,否则栈顶元素复制一份入栈。
算法感谢@阿当
如图所示,因为当前元素下有比它大的元素,所以这个元素的值事实上不会被用到,因此直接设置为栈顶元素即可。(如这里直接入栈7即可)
Code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 6 int n,top,x,op; 7 int stack[200050]; 8 9 int main() 10 { 11 memset(stack,0,sizeof(stack)); 12 scanf("%d",&n); 13 top=0; 14 for(int i=1;i<=n;i++) 15 { 16 scanf("%d",&op); 17 switch(op) 18 { 19 case 0: scanf("%d",&x); 20 stack[++top]=max(x,stack[top-1]); 21 break; 22 case 1: top--; break; 23 case 2: printf("%d\n",stack[top]); break; 24 } 25 } 26 return 0; 27 }