ロサンゼルスのソートバレーP1155デュアルスタック
トピックリンク:https://www.luogu.com.cn/problem/P1155
スタックの昇順は、知ることができる上部要素がスタックによってスタックにスタックからの転載であるスタック要素の底部よりも小さくなるように、単調スタックを維持すべきです
今すぐ[i]はスタック1を入力することはできません検討してください。
ただ、このような問題は、配列A中に存在する場合〔I〕<A Jは、A [i]は、[Jのシーケンスの順序場合 】 スタック、それは[Jのスタック順序ので、一定ではありません]、[I]、非昇順
しかし、i、jは必ずしも隣接して、我々は位置kであってもよいしません:私は<K <J時間は、そう[i]は、この時間をポップアップ表示することができます[i]は、[j]は、あなたが同じに入ることができるということのスタック
[i]を押すことができるときに最初)([I] <s1.topを必要とします。
(1)スタック2は空です。
現在時刻があっても、I <J <K [K] <[I] <[j]は、溶液とスタック2への[j]を、可能にすることができるので
(2)は、2つの非空のスタック、および配列は、I <J <K [K] <[I] <[J]、[J]> s2.top()が存在しません
if a[i]->s1
if a[j]->s1
because a[k]<a[i], so s1中有a[i]<a[j],且a[i]出栈晚于a[j],排除
if a[j]->s2
s2非空,分析一下什么元素会进s2.
假设s1和s2栈顶元素相等(当然题中不可能发生)那应该是弹s1较优,因为字典序更小。
假设s1栈顶元素>s2栈顶元素,不可能,因为字典序也不是最优
所以s2.top()>s1.top(),又因为a[j]>s2.top(),
所以a[j]>s2.top()>s1.top()>a[i]>a[k]
翻译一下这是啥意思呢,就是在a[k]未弹出时,a[j]没有地方可去,这是不行的
だから、オンライン上で解決貪欲、判定機能を記述します。
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n,a[N],now=1;
vector<char> ans;
stack<int> s,t;
void push1(int u){s.push(u);ans.push_back('a');}
void push2(int u){t.push(u);ans.push_back('c');}
void pop1(){s.pop();ans.push_back('b');}
void pop2(){t.pop();ans.push_back('d');}
bool check(int k)//a[k]<s.top()
{
if(t.empty()) return 1;
int i,j;//k<i<j
for(i=k+1;i<=n;i++) if(a[i]>a[k]&&a[i]>t.top()) break;
for(j=i+1;j<=n;j++) if(a[j]<a[k]) return 0;
return 1;
}
int main()
{
scanf("%d",&n);
int cnt=1;
s.push(1e4),t.push(1e4);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
bool ok=true;
for(int i=1;i<=(n<<1);i++)
{
if(s.top()==now) {pop1();now++;continue;}
if(t.top()==now) {pop2();now++;continue;}
if(cnt<=n&&a[cnt]<s.top()&&check(cnt)) {push1(a[cnt++]);continue;}
if(cnt<=n&&a[cnt]<t.top()) {push2(a[cnt++]);continue;}
ok=false;break;
}
if(ok)
{
for(int i=0;i<ans.size();i++)
if(i==0) putchar(ans[i]);
else printf(" %c",ans[i]);;
}
else puts("0");
return 0;
}