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

Posted zifeiy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一码学程 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;
}

以上是关于一码学程 10284 排队找bug 题解 单调队列 或者 线段树RMQ的主要内容,如果未能解决你的问题,请参考以下文章

题解P1419 寻找段落(二分+单调队列)难度⭐⭐⭐★

题解报告:poj 2823 Sliding Window(单调队列)

HDU 3415 Max Sum of Max-K-sub-sequence 单调队列题解

2096: [Poi2010]Pilots单调队列题解

[题解]luogu_P3084(单调队列dp

poj 2823题解