zoukankan      html  css  js  c++  java
  • L3-002 特殊堆栈 (30 分)

    大家都知道“堆栈”是一种“先进后出”的线性结构,基本操作有“入栈”(将新元素插入栈顶)和“出栈”(将栈顶元素的值返回并从堆栈中将其删除)。现请你实现一种特殊的堆栈,它多了一种操作叫“查中值”,即返回堆栈中所有元素的中值。对于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
    

    Pop和Push都好操作,可以用个数组维持一个栈,关键是求第k小的值(k = n / 2 || k = (n + 1)/ 2),栈的元素个数是变化的,线段树不太会用,所以用树状数组来记录,查找的时候用二分法查找。
    代码:
    #include <bits/stdc++.h>
    using namespace std;
    int t[100005],m;
    int lowbit(int t)
    {
        return t&-t;
    }
    void update(int x,int y)
    {
        for(;x <= 100000;x += lowbit(x))
        {
            t[x] += y;
        }
    }
    int getsum(int x)
    {
        int sum = 0;
        for(;x > 0;x -= lowbit(x))
        {
            sum += t[x];
        }
        return sum;
    }
    int query(int x)
    {
        int l = 1,r = m,mid,sum;
        while(l < r)///如果从1到mid一共不到x个数,就让l = mid + 1,但是如果大于或等于x都有可能,所以此时选最左边的值(即query(t)<x && query(t + 1)>=x 选t + 1),所以r = mid 不能让r = mid - 1,不然取的可能不是upper的值
        {
            mid = (l + r) / 2;
            sum = getsum(mid);
            if(sum >= x)r = mid;
            else l = mid + 1;
        }
        //l == r
        return l;
    }
    int main()
    {
        char s[10];
        int n,st[100000],c = 0;
        scanf("%d",&n);
        for(int i = 0;i < n;i ++)
        {
            scanf("%s",s);
            if(s[1] == 'u')
            {
                scanf("%d",&st[c]);
                if(st[c] > m)m = st[c];
                update(st[c ++],1);
            }
            else if(!c)
            {
                puts("Invalid");
            }
            else
            {
                if(s[1] == 'o')
                {
                    printf("%d
    ",st[-- c]);
                    update(st[c],-1);
                }
                else
                {
                    if(c % 2)printf("%d
    ",query((c + 1) / 2));
                    else printf("%d
    ",query(c / 2));
                }
            }
        }
    }
  • 相关阅读:
    JAVA_NIO 与Netty框架
    Socket编程
    P3368树状数组2(树状数组//改段求点)
    P3373 树状数组1(树状数组//改点求段)
    树状数组
    P1197 星球大战(并查集+链式向前星)
    P2024 食物链(种类并查集||带权并查集)
    P1111 修复公路(kruscal+并查集)
    P1387 最大正方形+P1736 创意吃鱼法(矩形上的dp+预处理)
    P2330 繁忙的城市(krusal最小生成树)
  • 原文地址:https://www.cnblogs.com/8023spz/p/8596459.html
Copyright © 2011-2022 走看看