L3-002. 堆栈【主席树 or 线段树 or 分块】

L3-002. 堆栈

时间限制
200 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越

大家都知道“堆栈”是一种“先进后出”的线性结构,基本操作有“入栈”(将新元素插入栈顶)和“出栈”(将栈顶元素的值返回并从堆栈中将其删除)。现请你实现一种特殊的堆栈,它多了一种操作叫“查中值”,即返回堆栈中所有元素的中值。对于N个元素,若N是偶数,则中值定义为第N/2个最小元;若N是奇数,则中值定义为第(N+1)/2个最小元。

输入格式:

输入第一行给出正整数N(<= 105)。随后N行,每行给出一个操作指令,为下列3种指令之一:

Push key
Pop
PeekMedian

其中Push表示入栈,key是不超过105的正整数;Pop表示出栈;PeekMedian表示查中值。

输出格式:

对每个入栈指令,将key入栈,并不输出任何信息。对每个出栈或查中值的指令,在一行中打印相应的返回结果。若指令非法,就打印“Invalid”。

输入样例:
17
Pop
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
Pop
Push 5
Push 4
PeekMedian
Pop
Pop
Pop
Pop
输出样例:
Invalid
Invalid
3
2
2
1
2
4
4
5
3
Invalid

 主席树和线段树网上有很多博客,但是算算时间复杂度,会发现用分块就可以水过了。

附ac代码(本人最近在改代码风格,所以排版很乱):

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <string>
 4 #include <iostream>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <map>
 8 #include <queue>
 9 #include <map>
10 #include <cmath>
11 #include <set>
12 using namespace std;
13 const int maxn = 200000;
14 int nu[maxn];
15 int num[maxn];
16 int bk[1000];
17 char s[111];
18 int main() {
19     int n,top=0,x;
20     int block=400;
21  //   printf("%dbb\n",block);
22     scanf("%d",&n);
23     for(int i=0;i<n;++i) {
24         scanf("%s",s);
25         if(s[1]=='u') {
26             scanf("%d",&x);
27             nu[x]++;
28             num[top++]=x;
29             bk[x/block]++;
30          //   printf("%d bk\n",x/block);
31         }
32         else if(s[1]=='e') {
33             if(top==0) {
34                 puts("Invalid");
35                 continue;
36             }
37             int u=(top+1)/2;
38            // printf("%d u\n",u);
39             int sum=0;
40             int j;
41             for(j=0;j<=block;++j) {
42                 sum+=bk[j];
43              //   printf("%d sum\n",sum);
44                 if(sum>=u) break;
45             }
46             for(int k=block-1;k>=0;--k) {
47                 sum-=nu[j*block+k];
48                 if(sum<u) {
49                     printf("%d\n",j*block+k);
50                     break;
51                 }
52             }
53         }
54         else {
55             if(top==0) {
56                 puts("Invalid");
57                 continue;
58             }
59             x=num[--top];
60             printf("%d\n",x);
61             nu[x]--;
62             bk[x/block]--;
63         }
64     }
65     return 0;
66 }
View Code

线段树方面,这个博客写的挺简洁的:戳这里

posted @ 2018-03-14 21:04  euzmin  阅读(225)  评论(0编辑  收藏  举报