1. 程式人生 > >p1321雙棧排序(noip2008)

p1321雙棧排序(noip2008)

題目

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