每日一题【二分图染色

题意:
给两个栈和一个排列
每次可以选择序列的第一个数入任何一个栈
或者让任一一个栈顶元素出栈
要求出栈顺序为1-n

思路:首先如果我们只有一个栈会要怎么做,2,3,1不是怎么入栈都不行吗?
那么我们可以考虑a[k]<a[i]<a[j] k<i<j,此时我们利用另一个栈来解决问题,
模拟的话感觉有点麻烦,是不是有更优的做法?
我们遇到这样a[i]<a[j]矛盾之后我们就把他们分两侧,之后还要判断是不是有冲突,类似奇数环的话就不行,这不就是二分图染色吗?染完色模拟输出就行🤷‍♂️

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>p;
const int N=1e6+5;
const int M=1e3+5;
const int mod=998244353;
int T,n,m;
int a[N], suff[N];
vector<int>G[N];
int col[N];
int dfs(int u,int c) {
    col[u]=c;
    for(auto v:G[u]) {
        if(col[v]==c)return 0;
        if(col[v]==-1&&!dfs(v,c^1))return 0;
    }
    return 1;
}

int main() {
    cin>>n;
    for(int i=1; i<=n; i++)scanf("%d",&a[i]);
    suff[n+1]=mod;
    for(int i=n; i>=1; i--)suff[i]=min(a[i],suff[i+1]),col[i]=-1;
    for(int i=1; i<=n; i++) {
        for(int j=i+1; j<=n; j++) {
            if(a[i]<a[j]&&suff[j+1]<a[i]) {
                G[i].push_back(j);
                G[j].push_back(i);
            }
        }
    }
    for(int i=1; i<=n; i++) {
        if(col[i]==-1&&!dfs(i,0)) {
            printf("0\n");
            return 0;
        }
    }
    string ans="";
    int now=1;
    stack<int>s1,s2;
    for(int i=1; i<=n; i++) {
        if(col[i]==0)
            s1.push(a[i]),ans+="a ";
        else s2.push(a[i]),ans+="c ";
        while(true) {
            if(!s1.empty()&&s1.top()==now)s1.pop(),ans+="b ";
            else if(!s2.empty()&&s2.top()==now)s2.pop(),ans+="d ";
            else break;
            now++;
        }
    }
    cout<<ans<<endl;
}