モノトーンスタック[Luogu P4248]

タイトル説明
長さを有しているが、\(N- \)配置(P_0、P_1、\ cdots、P_ {N--は1} \)\、この構成により長生成\(N- \)配列(\ S \) \(S_Iが\)で表される(P_0、P_1、\ cdots \ 、P_I \)は単調スタックサイズからなるインクリメントされます。

別の言い方をすれば、シーケンス\(S \)は、次のコードによって生成されます。

stack<int> stk;
int n = p.size();
vector<int> S;
for (int i = 0; i < n; i++) {
    while (!stk.empty() && p[i] <= p[stk.top()]) stk.pop();
    stk.push(i);
    S.push_back((int)stk.size());
}

今、あなたのシーケンス\(S \)部分の一部が与えられていない任意の値を取ることができます。分析してください\(S \)の配置復元\(P \)を辞書の可能な出力シーケンスの最小数がある場合。解ける保証。

[入力フォーマット
最初の行の整数\(N- \) 配列の長さを表示します。

次の行\(N- \) 整数、シーケンス\(S \) 前記アイテムが一部である- (1 \)\任意の値を取ることができます。

[]出力形式の
ライン\(N- \) 整数、順列。

ノーdaluoバレーレース月。しかし、この質問は、彼が時間半のカットオフを過ごしたので、やっているようです

問題の解決策

この全体の問題は、アイデアの貪欲+の再発であります

我々はによって決定したと\(S_1 \ SIM S_ {I -1} \) の導入によって辞書最小(1 \ SIM I-1 \ \) からなる整列\(P \) およびP(\ \ )電流増加単調スタック\(STK \)スタックは、要素の値の代わりに添字にここに格納されることに注意してください

それでは、どのように考える\(P \)に挿入された\(I \)この要素は、辞書順最小になり

しかし、挿入(I \)\我々は良い取引ではありません。この操作の

このオリジナルを検討することを望むかもしれない(P \)\すべてに\(\ GEは\ x)が 1のすべての要素を、その後に\(P \)エンドプラスで\(X \)を取得するためにこれを証明するのは簡単です\(pは\ )配列に対応する\(S_1 \ SIM S_ {iが -1} \) オリジナルと同じままであります

だから、\(X \)の条件を作るために満たされているものに(\ S_I)は\正確に値を考慮することが必要である(I-1は、\)\スタック単調に増加する\(STK \)でなければならない[\(STK S_i-を1] <X \ルSTK [ S_I] \) そのような\(STK [S_I] \ SIM STK [トップ] \) であろうポップアップ

辞書的に私たちを聞かせて見かけ最小限にするために(X = STK [S_I] \ \) 、その後、我々は転送を取得します

以下のようなアルゴリズムのプロセスは、次のとおりです。

知ら:によって辞書式に最小(1 \ SIM I-1 \ \) 満たす構成(S_1 \ SIM S_ {I \ -1} \) 必要アライメント\(P \)\(P \)現在単調増加スタック\(STK \)サイズ\(トップ\)

テイク(X = STK [S_I] \ \) 現在の\(P \)全てに\(\ GEは\ X) 次いで+1要素を\(X \)\(P \)スタック更新モノトーンの終わりに

\(S_I = -1 \)または\(S_I>トップ\)直接\(I \)スロー\(P \) それの終わりに

しかし、我々は、これは発見している必要があります\(O(N ^ 2) \) の

より多くのすべてよりナッシング(\ GEは、X \)\要素+1このステップは時間がかかりすぎるか\(O(1)\)または\((Nログ\)O \) それを解決するために?

何がないのは、巧妙なトリックや邪悪な工芸品のデータ構造である♂

1.私たちが望む場合は、\(I \を)\(P \)最後に当社が保有する(\ I)を\我々は入れ\(I * 1000005 \) または任意の大きい乗じたより(N- \を\)数)

2.私たちが作るのであれば、\(X = STK [S_I] \) 、その後、現在の\(P \)すべてで(\ GEは\ x)が\私達はちょうど聞かせする必要はありません+1 +1要素\(X = STK [S_I] -1 \)次にビン端部に配置されています

最後には限界が予選た場合でも、正しい答えを得るために個別の外観の順序を行に答えを得るのですか(P \)\です\(nは\ simの1 \)私たちは、乗算数がより大きいので、逆の配置が\ (N \)間違っていることはありません

時間複雑\(O(N \ Nログ )\) かどうかを知りません\(O(N)\)の練習をしてますが、コードので、\(\ログ\)のみであるsortので、RAN \(1E6 \)または何の圧力はありません

コード

#include <bits/stdc++.h>
using namespace std;
typedef long long ll; 

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    for (; ch > '9' || ch < '0'; ch = getchar()) if (ch == '-') f = -1;
    for (; ch <= '9' && ch >= '0'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ '0');
    return x * f;
}

int n, a[1000005], top;
ll stk[1000005], ans[1000005], srt[1000005], mx;

int main() {
    n = read(); 
    for (int i = 1; i <= n; i++) {
        a[i] = read();
    }
    for (ll i = 1; i <= n; i++) {
        if (a[i] == -1) {
            ans[i] = i * 1000005;
            stk[++top] = ans[i];
        } else {
            if (a[i] > top) {
                ans[i] = i * 1000005;
                stk[++top] = ans[i];
            } else {
                ans[i] = stk[a[i]] - 1;
                stk[top = a[i]] = ans[i];
            }
        }
    }
    for (int i = 1; i <= n; i++) srt[i] = ans[i];
    sort(srt + 1, srt + n + 1);
    for (int i = 1; i <= n; i++) ans[i] = lower_bound(srt + 1, srt + n + 1, ans[i]) - srt;
    for (int i = 1; i <= n; i++) printf("%lld ", ans[i]);
    return 0;
} 

おすすめ

転載: www.cnblogs.com/ak-dream/p/AK_DREAM49.html