题目大意

要求维护一个栈,提供压栈、弹栈以及求栈内中位数的操作(当栈内元素\(n\)为偶数时,只是求第\(n/2\)个元素而非中间两数的平均值)。最多操作100000次,压栈的数字\(key\)范围是[1,100000]。

题目分析

前两个操作用\(stack\)就好。

求中位数。暴力做法即使用上优先队列也是稳稳的超时。考虑树状数组。

压栈时,将\(key\)值对应的位置加1。弹栈减1。

求中位数,可以二分求出\(sum[1:p]==(n+1)/2\)最小的\(p\),即为\(ans\)。复杂度\(O(nlog^2n)\)。

问题已被解决,但是还有进一步优化的空间。

考虑倍增(?)。从高到低枚举\(ans-1\)的每一个二进制位,即求最大的\(p\)使得\(sum[1:p]<(n+1)/2\)。我们知道树状数组\(tree[k]=\sum_{i=k-lowbit(k)+1}^knum[i]\),也就是说如果我们知道\(\sum_{i=1}^knum[i]=A\)且\((1<<j)<lowbit(k)\),那么\(\sum_{i=1}^{k+(1<<j)}=A+tree[k+(1<<j)]\)。倍增的时候枚举二进制位的时候,恰巧我们也是从大到小枚举的,满足\(j\)与\(k\)的限制。这样,就将一次树状数组上\(logn\)的查询替换成一次简单的加法。复杂度\(O(nlogn)\)。

#include <bits/stdc++.h>

using namespace std;

int num;

stack<int> st;

int sum[100005];

int lowbit(int x) {return x & -x;}

void add(int p, int v) {for (int i = p; i <= 100000; i += lowbit(i)) sum[i] += v;}

/*
int get(int p) {
    int ret = 0;
    for (int i = p; i >= 1; i -= lowbit(i)) ret += sum[i];
    return ret;
}
*/

int main() {
    num = 0;
    while (!st.empty()) st.pop();
    memset(sum, 0, sizeof(sum));

    int n;
    scanf("%d", &n);
    for (int _ = 0; _ < n; ++_) {
        char com[20];
        scanf("%s", com);
        if (strcmp(com, "Push") == 0) {
            int key;
            scanf("%d", &key);
            ++num;
            st.push(key);
            add(key, 1);
        } else if (strcmp(com, "Pop") == 0) {
            if (!st.empty()) {
                int key = st.top();
                printf("%d\n", key);
                --num;
                st.pop();
                add(key, -1);
            } else printf("Invalid\n");
        } else {
            if (!st.empty()) {
                int temp = 0, ans = 0;
                for (int i = 16; i >= 0; --i) {
                    if (ans + (1 << i) > 100000) continue;
                    if (temp + sum[ans + (1 << i)] < (num + 1) / 2) temp += sum[ans += (1 << i)];
                }
                printf("%d\n", ans + 1);
            } else printf("Invalid\n");
        }
    }
    return 0;
}

PAT1057 Stack(树状数组+倍增)的更多相关文章

  1. 【bzoj2819】Nim DFS序+树状数组+倍增LCA

    题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...

  2. 1057 Stack 树状数组

    Stack is one of the most fundamental data structures, which is based on the principle of Last In Fir ...

  3. Luogu P4901 排队 fib数列+树状数组+倍增

    这题让我升华..还好只重构了一遍 首先我们发现:$n$较小时,整个队伍的形态 跟 $n$ 比较大时的局部是一样的 所以我们预处理出这个队伍的形态,和每一行每个位置的质因子个数的前缀和,$O(nlogn ...

  4. CF786C-Till I Collapse【树状数组倍增,优先队列】

    正题 题目链接:https://www.luogu.com.cn/problem/CF786C 题目大意 给出一个长度为\(n\)的序列. 对于每个\(k\in[1,n]\)求将\(n\)分成最少的段 ...

  5. 【BZOJ2819】Nim 树状数组+LCA

    [BZOJ2819]Nim Description 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可 ...

  6. PAT-1057 Stack (树状数组 + 二分查找)

    1057. Stack Stack is one of the most fundamental data structures, which is based on the principle of ...

  7. BZOJ 2819: Nim dfs序维护树状数组,倍增

    1.随机选两个堆v,u,询问若在v到u间的路径上的石子堆中玩Nim游戏,是否有必胜策略,如果有,vfleaking将会考虑将这些石子堆作为初始局面之一,用来坑玩家.2.把堆v中的石子数变为k. 分析: ...

  8. 1057. Stack (30) - 树状数组

    题目如下: Stack is one of the most fundamental data structures, which is based on the principle of Last ...

  9. PAT甲级1057 Stack【树状数组】【二分】

    题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805417945710592 题意:对一个栈进行push, pop和 ...

随机推荐

  1. markdown总结 (webstrom快捷键)

    # 在HbuilderX中写markdown(WebStrom快捷键配置)0. 一些快捷键和鼠标操作:1. ctrl+shift+↑  当前行或者选中的块整体向上移动  ↓同理2. 向两侧扩大选择:A ...

  2. 找到了element, 但是用getText却得到空值,取不到文本的解决办法

    最近代码中发现一些bug, 在Debug过程中发现,页面元素是被定位到了,但是用getText方法取到的却是空值.调查了一下发现,getText是否返回值和isDisplayed是否为true有关.当 ...

  3. API更新#图书信息查询ISBN2.0

    ISBN图书查询     自2019年5月8日公布isbn查询接口1.0至今,该图书数据查询服务已被调用八万余次,查得图书11653本,感谢一直使用和关心这个接口的朋友们! 目前网站域名将于2019年 ...

  4. python爬虫项目-一见倾心壁纸

    方法1 import re import urllib import urllib.request def getHtml(url): page = urllib.request.urlopen(ur ...

  5. Java中的compareTo()方法,compareToIgnoreCase()方法

    1.compareTo(String)方法: Java中String类有一个compareTo方法,该方法返回一个int类型的数据.其比较规则是:拿出字符串的第一个字符与参数的第一个字符进行比较,如果 ...

  6. csrf与xss

    CSRF攻击攻击原理及过程如下: 1. 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A:       2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登 ...

  7. 设计模式之代理模式--PHP

    代理模式是常用的设计模式之一,代理模式为对象的间接访问提供了一套方案,可以对对象访问进行控制,也能监控对象访问相关的数据信息. 代理模式(Proxy)就是给某一个对象提供代理,在由代理控制原对象的访问 ...

  8. 【Android - 控件】之V - Toolbar的使用

    Toolbar是Android V7包中的一个控件,用来代替Action Bar作为界面的头部标题栏布局.Toolbar相对于Action Bar的特点是更加灵活,可以显示在任何位置. 首先先来看To ...

  9. vim介绍、颜色显示和移动光标、一般模式下移动光标及复制、剪切和粘贴

    第4周第4次课(4月12日) 课程内容: 5.1 vim介绍5.2 vim颜色显示和移动光标5.3 vim一般模式下移动光标5.4 vim一般模式下复制.剪切和粘贴 5.1 vim介绍 centos7 ...

  10. 个人搭建后台管理模板 Bootstrap4 ,ASP.NET Core,EF Core,JWT

    拥有一个美观好用的网站后台,是很多开发者的梦想,笔者在闲暇时间里搭建了一个不错的后台框架,这里分享诸位开发同仁. 项目地址:https://github.com/kongdf123/KentNoteB ...