p1321雙棧排序(noip2008)
阿新 • • 發佈:2018-12-02
題目
https://www.luogu.org/problemnew/show/P1155
題解
二分圖判定+模擬題目要求的雙棧進出
程式碼
#include<bits/stdc++.h>
using namespace std;
const int inf=0x7f7f7f7f;
const int __=1010;
inline int read()
{
int f=1,num=0;
char ch=getchar();
while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); }
while (isdigit (ch)) num=(num<<1)+(num<<3)+(ch^48), ch=getchar();
return num*f;
}
vector<int> e[__];//用了不定陣列來建立鄰接表
stack<int> s1,s2;
int f[__],a[__];
int color[__];
void bfs(int s)
{
queue<int>q;
q.push(s);
color[s]=1;
while (!q.empty())
{
int x=q.front();
for (int i=0;i<e[ x].size();++i)
{
int y=e[x][i];
if (color[y]==-1)
{
color[y]=color[x]^1;
q.push(y);
}
else if (color[y]!=(color[x]^1))
{
cout<<0;
exit(0);
}
}
q.pop();
}
}
int main()
{
//讀入資料
memset(color,-1,sizeof(color));
int n=read();
for (int i=1;i<=n;++i)
a[ i]=read();
/*
用動態規劃的思想,將上述複雜度降到O(n^2)
狀態:f[i]=min(a[i],a[i+1], ... ,a[n])
邊界條件:f[n+1]=INF;
狀態轉移方程:f[i]=min(f[i+1],a[i])
於是下述判斷就轉化為了 f[j+1]<a[i] && a[i]<a[j]
*/
f[n+1]=inf;
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])
e[i].push_back(j),e[j].push_back(i);
//二分圖染色
for (int i=1;i<=n;++i)
if (color[i]==-1)
bfs(i);
//開始模擬雙棧排序
int cnt=1;
for (int i=1;i<=n;++i)
{
if (color[i]==1)
{
s1.push(a[i]);//染成黑色的進入一棧
cout<<"a ";
}
else
{
s2.push(a[i]);//染成白色的進入二棧
cout<<"c ";
}
while ((!s1.empty()&&s1.top()==cnt) || (!s2.empty()&&s2.top()==cnt))
{
if (!s1.empty()&&s1.top()==cnt)
{
s1.pop();
cout<<"b ";
}
else
{
s2.pop();
cout<<"d ";
}
++cnt;
}
}
return 0;
}