一码学程 10284 排队找bug 题解 单调队列 或者 线段树RMQ

注:只是看到题目,未评测,所以不确定代码正确性,但是算法思路没有问题

描述

同学们的bug还真是多啊,orz...
春节期间大家存下的bug都来找肖老师解决了。
每个人都有bug,但是肖老师却只有一个啊。怎么办?
所以肖老师让大家按先来后到的顺序排队,一个一个的给大家解决。
这不一大早起来,肖老师就等着同学们过来解决bug了。不过肖老师偶尔想知道当前队伍中bug数量最少的是多少bug。
sos xbug操作表示有一个同学有x个bug,并且过来排队等待肖老师解决。
ok 操作表示肖老师已经解决了排在队伍最前面同学的所有bug。
min 操作表示肖老师需要知道当前排队队伍中bug数量最少的是多少bug。

输入格式

第一行输入一个正整数n,表示总共有n种操作。
接下来输入n行,每行一种操作。
【限制条件】
1≤n≤10^6
每个人的bug数量不超过1000000。

输出格式

对于每一次min操作,输出当前排队中bug最少的数量。
如果执行min(或者ok)操作时,当前队伍为空,则输出“So happy!No bug!”。

样例输入

7
sos 6bug
sos 7bug
min
ok
min
ok
min

样例输出

6bug
7bug
So happy!no bug!

这道问题可以用单调队列求解,代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000100;

/**
* zifeiy: 单调队列解法
*/

queue<int> normal_que;
deque<int> min_que;
int a[maxn], n, cnt = 0;
string s;

int main() {
    cin >> n;
    while (n --) {
        cin >> s;
        if (s == "sos") {
            scanf("%dbug", &a[cnt]);
            normal_que.push(cnt);
            while (!min_que.empty()) {
                int u = min_que.back();
                if (a[u] >= a[cnt]) min_que.pop_back();
                else break;
            }
            min_que.push_back(cnt);
            cnt ++;
        }
        else if (s == "ok") {
            if (normal_que.empty()) {
                puts("So happy!No bug!");
            } else {
                int u = normal_que.front();
                normal_que.pop();
                while (!min_que.empty() && min_que.front() <= u) {
                    min_que.pop_front();
                }
            }
        }
        else {  // "min"
            if (min_que.empty()) {
                puts("So happy!No bug!");
            } else {
                cout << a[min_que.front()] << "bug" << endl;
            }
        }
    }
    return 0;
}

也可以转换成求解RMQ问题,我这里使用线段树来实现RMQ:

#include <bits/stdc++.h>
using namespace std;
#define INF (1<<29)
const int maxn = 1000100;

/**
* 使用线段树实现RMQ的解法
*/

int minn[maxn<<2], n, m, a;
vector<int> vec;
vector<int> queries;    // 0表示sos,1表示min,2表示ok
char ch[111];

void build(int l, int r, int rt) {
    if (l == r) minn[rt] = vec[l];
    else {
        int mid = (l + r) >> 1;
        build(l, mid, rt<<1);
        build(mid+1, r, rt<<1|1);
        minn[rt] = min(minn[rt<<1], minn[rt<<1|1]);
    }
}

int query(int L, int R, int l, int r, int rt) {
    if (L <= l && r <= R) return minn[rt];
    int mid = (l + r) >> 1;
    int tmp = INF;
    if (L <= mid) tmp = min(tmp, query(L, R, l, mid, rt<<1));
    if (mid+1 <= R) tmp = min(tmp, query(L, R, mid+1, r, rt<<1|1));
    return tmp;
}

int main() {
    scanf("%d", &m);
    for (int i = 0; i < m; i ++) {
        scanf("%s", ch);
        if (strcmp(ch, "sos") == 0) {
            scanf("%dbug", &a);
            vec.push_back(a);
            queries.push_back(0);
            n ++;
        }
        else if (strcmp(ch, "min") == 0) {
            queries.push_back(1);
        }
        else {
            queries.push_back(2);
        }
    }
    build(0, n-1, 1);
    int L = 0, R = -1;

    for (int i = 0; i < m; i ++) {
        if (queries[i] == 0) R ++;
        else if (queries[i] == 2) L ++;
        else {  // 1 - min
            if (L > R) puts("So happy!no bug!");
            else printf("%dbug\n", query(L, R, 0, n-1, 1));
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zifeiy/p/10955712.html

时间: 2024-10-02 22:52:28

一码学程 10284 排队找bug 题解 单调队列 或者 线段树RMQ的相关文章

HDU5957 Query on a graph(拓扑找环,BFS序,线段树更新,分类讨论)

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5957 题意:D(u,v)是节点u和节点v之间的距离,S(u,v)是一系列满足D(u,x)<=k的点的集合,操作1:将S(u,k)内节点权值增加或者减小,操作2:查询S(u,k)内节点的权值和 题解:因为题目说了查询和更新的距离小于等于k,k最大为2,所以很显然要分情况讨论k为0.1.2的情况 因为是多次更新,我们显然是需要用线段树来维护节点权值的 运用线段树和bfs序的知识我们知道 对一个棵树求BFS

Java读源码学设计模式:适配器Adapter

适配器模式相关源码:slf4j-1.6.1.hibernate-3.6.7 大家都知道,log4j是一个广泛使用的日志工具,除此之外,sun公司在JDK中也有自己的日志工具,也就是java.util.logging.Logger.当然还有其他一些日志工具. 多种日志工具功能和使用方式类似,一般都包含debug.info.warn.error等日志级别的方法,但却没有实现共同的接口.这一点不像JDBC,虽然关系型数据库种类很多,例如MySQL.Oracle等,但是有一套统一的接口,也就是JDBC.

【软件测试】软件测试是找bug,不是找茬

前两天和一个新认识的朋友聊天 "你是码农吗?" 我那个气啊,我这个形象像吗?像吗?真想抽他丫的 "不是,我是做软件测试的,代码用的没有那么多,所以称不上" "哦!那你就是专门挑毛病,找茬的呗?" 当时我就认定了这个朋友拜拜了您内 "我是做测试的,找的是缺陷,不是找茬,谢谢您老了,先忙,再见" 回家了之后我就想分享一下: 第一: 测试是找bug,不是找茬.以前在外包做测试,面对的之间人是PM,面对所谓的客户是开发软件的人,而且因

从LLVM源码学C++(五)

知识点:static,const,static const 详解:转(http://blog.csdn.net/yjkwf/article/details/6067267) const定义的常量在超出其作用域之后其空间会被释放,而static定义的静态常量在函数执行后不会释放其存储空间. static表示的是静态的.类的静态成员函数.静态成员变量是和类相关的,而不是和类的具体对象相关的.即使没有具体对象,也能调用类的静态成员函数和成员变量.一般类的静态函数几乎就是一个全局函数,只不过它的作用域限

从LLVM源码学C++(四)

关键知识点:断言 1 const Option OptTable::getOption(OptSpecifier Opt) const { 2 unsigned id = Opt.getID(); 3 if (id == 0) 4 return Option(0, 0); 5 assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID."); 6 return Option(&getInfo(id

从LLVM源码学C++(三)

关键知识点:mutable关键字 mutable关键字: mutalbe的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词. 在C++中,mutable也是为了突破const的限制而设置的.被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中. 我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的.但是,有些时候,我们需要在const的函数里面修改一些跟类状态无关的数据成员,那么这个数据成员就应该被mut

学EE做硬件找工作不如学CS做软件,为什么会这样?

学EE做硬件找工作不如学CS做软件,为什么会这样? 电子工程(EE)就业最好的方向居然是转计算机,也许让有的人觉得很不公平,EE也是很重要的学科,我们学习也很努力,为什么就业会不如CS?也有的人好奇,EE/硬件也是信息技术行业不可缺少的一部分,为啥CS软件工作机会这么多而EE硬件不行? 最主要的原因就是一个字:钱. 一个行业要发展要兴旺,要有资金投入.信息技术行业的发展,并不是靠政府资金驱动的,而是私人投资.投资人当然希望风险尽可能的少.回报尽可能大的快,而且收回成本要尽可能的快. 要做软件开发

从LLVM源码学C++(一)

今天开始需要分析clang的源码了,LLVM这个开源的project代码写的很不错的,也算是巩固一下C++的一些基础知识了. 首先是在llvm/ADT/OwningPtr.h中定义了owningptr智能指针的实现: 源码如下: 1 /// OwningPtr smart pointer - OwningPtr mimics a built-in pointer except that it 2 /// guarantees deletion of the object pointed to,

从LLVM源码学C++(二)

在看Clang源码的过程中遇到过,返回const引用,于是就去google 了一下返回值以及参数传递等相关的知识. 首先,为什么要(const 引用)的返回值? 首先&的引用作用是C++独有的特性.其作用相当于传入参数时不经过拷贝,而是实实在在的传入. fun(int &a).如果在函数内部修改了a的值,那就确实修改了a的值.而一般的参数传入方式都是传入一个参数的副本.函数内部的操作都是作用于副本. 对于返回值,也类似.一般返回值也是返回的拷贝值.所以如果将函数内的局部变量以引用方式返回是