モノトーンキューセグメントツリーRMQバグや問題の解決策を見つけるために10284科学1ヤードラインドライブ

注意:ちょうどタイトルではなく、評価、コードのように不確実な妥当性を見ましたが、アルゴリズムの考え方は問題ありません

説明

学生のバグは本当にああ、ORZ ...、である
私たちは春祭りが解決ショウに来た時のバグを保存することができます。
誰もがバグを持っていますが、ショーは唯一の教師のああです。方法は?
ショーのみんなしたがって、最初の最初に来る誰もが解決するために、キュー、一つ一つを務めたことで。
これは、学生がバグを解決するために来るのを待って、早朝にシャオの先生ではありません。しかし、ショーは時折バグチームの現在の最小数ははるかにバグであるかを知りたいです。
SOS xbug操作は、学生がバグのx数を持っていることを示し、そしてショーが解決キューに入って来ます。
OK操作はショーは、すべてのバグが生徒の前のランクに来て解決してい表します。
分操作表し暁の先生は、現在のラインアップのチームの最小数はバグバグの数であるかを知る必要があります。

入力形式

正の整数nの第一の入力線と、n個存在する合計演算を表します。
次のn個の入力ライン、動作の各行。
[制限]
1≤n≤10^ 6
バグ番号それぞれの人ではない100万人以上。

出力フォーマット

各操作分間、最小出力電流キューイングバグの数。
実行分(または[OK])操作は、現在のチームが空の場合、出力「だから幸せ!ノーバグ!」 。

サンプル入力

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;
}

おすすめ

転載: www.cnblogs.com/zifeiy/p/10955712.html