羅区1155:デュアルスタックソート
質問の説明の意味:
- 長さを考えると\(N- \)シーケンス\((N- \のLeq 1000)\)、2つの最初は空のスタック、および昇順で4行の動作のシーケンスかどうかを尋ねました。
- \(1:\)配列が空でない場合、スタック上の最初の要素\(S_1 \) 。操作はと呼ばれる\(\) 。
- \(2:\)スタック場合\(S_1 \)は、空でない\(S_1 \)出力シーケンスを吐出するトップ要素。動作と呼ばれる\(D \) 。
- \(3:\)入力シーケンスが空でない場合、スタック上の最初の要素\(S_2 \) 。動作と呼ばれる\(C \) 。
- \(4:\)スタック場合\(S_2 \)は、空でない\(S_2 \)出力シーケンスを吐出するトップ要素。動作と呼ばれる\(D \) 。
出力説明:
- 出力動作辞書順最小のシーケンス、そうでない場合は、ソートデュアルスタックの性質上、出力\(0 \) 。
アイデア:
- 長いスタック単調貪欲+ +アナログの書き込みは二部グラフを思い出すべきです。
- 私は問題を解決するには、3時間の経過を記念書きます。
- まず、このような文字があります。
- この条件が存在する場合、\を(私は<jの<K \ ) と\((K)<(I)<(J)\) 、次いで\((I)、 (J)は\) にすることはできません必要十分条件である、同じスタック内。
- 証明:
- 要:場合\は、(iがjを<<K \ ) と\((K)<(I)<(J)\) 、それ以来、\((I)\)と\((J )\)は、後ろに少ない数が存在する\((K)\)、そう\((I)、 (J)\) スタックからポップされません。だから、要素のスタックの最上位にスタックの底から単調に減少降順ではありませんので、その後、ときと逆の順序がポップアップ表示されます\((I)、 (j)は\) 同じスタックに割り当てることはできません。
- 充足:場合は\((i)は、 (J)\) の条件が満たされない場合、競合が運転中に発生しません。
- 全ての粒子よりも大きい\((J)\)スタック内の要素が一定です。
- 全て未満\((J)\)の要素、例えば、\((I)<(J)\) 、によるバックの不在に\((K)<(I)\) 、そう\ ((I)\)ポップされています。
- したがって、\((j)が\)スタックにプッシュ、スタックの底部から上部にスタックが依然として下降維持することができ、全体の処理が円滑に行われます。
- 上記の自然と、我々は唯一の2つのスタックへのポイントのすべての条件を満たしている必要があり、このステップでは、グラフ理論の問題に変換することができます。
- 場合は、すべてのポイントを列挙\は、(i、jは\) 、その後、スタックが可能な条件を満たして(I、Jの\)\プラス側。
- もちろん、アカウントに上記の条件を取るのすべてのポイントを列挙し、非常に悪いことが起こるでしょう。
- 私は列挙する必要性を指し示す\(O(N ^ 2) \) 時間複雑、と私は後方小さい番号が必要とされてスキャンする必要はありません見つける(O(n)は\)\合計時間の複雑さを、それがされます(O(N ^ 3)\)\、渡すことはできません。
- この手順を最適化する方法を見つけるために、我々は、前処理とすることができます\(F(i)を=分(a_j)\) 。\(J \)から\(私は\)に\(\ N-) 。
- これは、とすることができる\(O(N ^ 2) \) か否かを判断する、列挙点\(I、Jの\)は、つまり、条件を満足\(1 + F_ {J} <a_iを<a_j \) 。
- その後、染色可能なデュアルスタックソートの性質を満たしているかどうかを決定するために、二部グラフかどうかを決定します。
- そして辞書最小要件ので、優先度ポイントに割り当てられているので、\(S_1 \)です。
- アナログデュアルスタックをソートした後、答えます。
複雑性分析:
- 図列挙を構築し、すべての点\(O(^ N-2)\) 。
- 染色は、2部グラフ決定\(O(N-M +)を\) 。
- アナログソートスタック\(O(N)\) 。
- 合計時間の複雑さは、\(O(^ N-2)\) 、通過することができます。
コード:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 10;
const int INF = 0x3f3f3f3f;
int n, a[maxn], f[maxn];
int head[maxn], ver[maxn<<5], nex[maxn<<5], tot;
inline void add_edge(int x, int y){
ver[++tot] = y; nex[tot] = head[x]; head[x] = tot;
}
int color[maxn];
bool dfs(int x, int c)
{
color[x] = c;
for(int i = head[x]; i; i = nex[i])
{
int y = ver[i];
if(!color[y])
{
if(!dfs(y, 3 - c)) return false;
}
else if(color[y] == c) return false;
}
return true;
}
int main()
{
scanf("%d", &n); f[n+1] = INF;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = n; i >= 1; i--) f[i] = min(f[i+1], a[i]);
for(int i = 1; i < n; i++)
for(int j = i + 1; j < n; j++)
if(a[i] > f[j+1] && a[i] < a[j])
add_edge(i, j), add_edge(j, i);
bool flag = true;
for(int i = 1; i <= n; i++)
{
if(!color[i])
{
if(!dfs(i, 1))
{
flag = false;
break;
}
}
}
if(flag == false) puts("0");
else
{
stack<int> stk1, stk2;
int cnt = 1;
for(int i = 1; i <= n; i++)
{
if(color[i] == 1)
{
stk1.push(a[i]);
printf("a ");
}
else{
stk2.push(a[i]);
printf("c ");
}
while((!stk1.empty() && stk1.top() == cnt) || (!stk2.empty() && stk2.top() == cnt))
{
if(!stk1.empty() && stk1.top() == cnt)
{
stk1.pop();
cnt++;
printf("b ");
}
else
{
stk2.pop();
cnt++;
printf("d ");
}
}
}
}
return 0;
}