雙棧排序(二分圖染色+模擬)
阿新 • • 發佈:2018-10-12
add bool 棧排序 void 不能 div color png turn
題目鏈接 https://www.luogu.org/problemnew/show/P1155
一開始我還以為能直接模擬=-=,太天真了...寫了好久對了3個點...看了題解之後恍然大悟,先二分圖匹配一下確定每個點在哪個棧裏頭再模擬會輕松很多。可怎麽建邊呢?
我們先從單棧排序開始:
可以的出的是,對於i,j,若存在k使得i<j<k,且A[k]<A[i]<A[j]的時候,是一定不能單棧排序的
就像3 4 1這樣的數,因為要保證小的先出來,
我們可以在這樣的i,j間建邊,用f[i]存i之後最小的數,這樣就可以把復雜度降到n的平方
之後就可以二分圖染色了=-=,染色時要註意1-n不一定時聯通的,所以要for一遍把所有都染掉
然後就是模擬了=-=字典序有點惡心,但只要時刻保證先出來在進去,先考慮s1,再考慮s2就可以了
代碼:
#include<cstdio> #include<cstdlib> #include<stack> #include<queue> #include<cstring> using namespace std; const int N=1010; int f[N],A[N]; struct node{ int nu,ne; }edge[N*N]; int tot,n; int col[N],head[N],belong[N];char ans[N*2]; bool vis[N]; void add(int a,int b) { edge[++tot].nu=b; edge[tot].ne=head[a]; head[a]=tot; } bool bfs(int st) { queue<int>q; q.push(st); col[st]=1; vis[st]=true; while(!q.empty()) { int a=q.front(); q.pop();for(int i=head[a];i!=-1;i=edge[i].ne) { int k=edge[i].nu; if(col[k]==col[a])return false; if(vis[k]) continue; vis[k]=true; col[k]=col[a]==1?2:1; q.push(k); } } return true; } int main() { memset(head,-1,sizeof(head)); stack<int>s1,s2; int bj=1,cnt=0; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&A[i]); memset(f,0x3f,sizeof(f)); A[n+1]=1e7; 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[j]>A[i]&&A[i]>f[j+1]) add(A[i],A[j]),add(A[j],A[i]); for(int i=1;i<=n;i++) if(!col[A[i]]) if(!bfs(A[i])) return printf("0\n"),0; for(int i=1;i<=n;i++) { if(col[A[i]]==1) belong[A[i]]=1; if(col[A[i]]==2) belong[A[i]]=2; } for(int i=1;i<=n;i++) { int a=belong[A[i]]; while(!s1.empty()&&s1.top()==bj) { bj++; s1.pop(); ans[++cnt]=‘b‘; } while(!s2.empty()&&s2.top()==bj) { bj++; s2.pop(); ans[++cnt]=‘d‘; } if(a==1) { s1.push(A[i]); ans[++cnt]=‘a‘; } if(a==2) { s2.push(A[i]); ans[++cnt]=‘c‘; } } while(!s1.empty()&&!s2.empty()) { if(s1.top()<s2.top()) { s1.pop(); ans[++cnt]=‘b‘; } else { s2.pop(); ans[++cnt]=‘d‘; } } while(!s1.empty())s1.pop(),ans[++cnt]=‘b‘; while(!s2.empty())s2.pop(),ans[++cnt]=‘d‘; for(int i=1;i<=cnt;i++) printf("%c ",ans[i]); return 0; }
雙棧排序(二分圖染色+模擬)