zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",u);
    39             int sum=0;
    40             int j;
    41             for(j=0;j<=block;++j) {
    42                 sum+=bk[j];
    43              //   printf("%d sum
    ",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
    ",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
    ",x);
    61             nu[x]--;
    62             bk[x/block]--;
    63         }
    64     }
    65     return 0;
    66 }
    View Code

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

  • 相关阅读:
    Elastic-Job分布式任务调度
    java.sql.BatchUpdateException: ORA-01861: 文字与格式字符串不匹配
    oracle锁表和解锁
    sql ibatis
    唯一索引
    斐波那契数列
    旋转数组的最小数字
    两个栈来实现一个队列
    重建二叉树
    重写和重载
  • 原文地址:https://www.cnblogs.com/zmin/p/8570121.html
Copyright © 2011-2022 走看看