1. 程式人生 > 實用技巧 >雙棧排序

雙棧排序

感覺有一些地方沒有梳理通,需要重新考慮一遍。

一開始的建圖,是沒有問題的。

對於任意三元組 \((x,y,z)\),若滿足 \(x<y<z\)\(a_x<a_y\)\(a_x>a_z\),那麼 \(x,y\) 之間便有一條之間相連的邊。

關鍵在於我後面的使用非常的 Naive,才導致 WA 掉。

比如對於:

10
10 2 8 1 7 9 3 4 5 6

顯然 \(7\)\(9\) 是無法放在同一組的,但 \(8\)\(9\) 也無法放在同一組,此時輪到 \(7\) 時應當塞進第二個棧。

但如何讓程式碼去考慮這類事情?

再次理解一下連邊的含義:

一條邊 \(x\to y\)

代表的是當 \(y\) 考慮入棧的時候,\(x\) 必定在棧內(具體哪個不清楚),且 \(y\) 不能和 \(x\) 在同一個棧內。

但是間接相連的就沒有 必定在棧內 這個性質。

這裡是可以直接由 \(9\) 向前面的 \(8\)\(7\) 各連了一條邊推斷出 \(7\)\(8\) 在同一個棧內。

然後重新考慮一下前面建邊的事情,其實是:

找到最右邊一個小於自己的位置,然後在這左邊的所有大於自己的點都連一條邊。

那麼考慮兩條邊 \(x\to y\)\(x\to z(x<y<z)\),由前面的結論可得:若 \(a_y<a_z\),則必定有邊 \(y\to z\)

\(\cdots\)

二分圖染色。

艹,我是 sb。

#include <stdio.h>
#include <string.h>
#include <vector>
#define LL long long
using namespace std;
const int N=1e3+3;
inline int min(int x,int y){return x<y?x:y;}
inline int rin()
{
    int s=0;
    bool bj=false;
    char c=getchar();
    for(;(c>'9'||c<'0')&&c!='-';c=getchar());
    if(c=='-')bj=true,c=getchar();
    for(;c>='0'&&c<='9';c=getchar())s=(s<<1)+(s<<3)+(c^'0');
    if(bj)s=-s;
    return s;
}

int n;
int a[N];
int s[N];
vector<int>to[N];
inline void add(int x,int y)
{
    to[x].push_back(y);
    to[y].push_back(x);
    return;
}

int dep[N];
bool vit[N];
bool if_true;
inline void dfs(int now,int fa)
{
    dep[now]=dep[fa]+1;
    vit[now]=true;
    for(int i=to[now].size()-1;i>=0;i--)
    {
        int nxt=to[now][i];
        if(nxt==fa)continue;
        if(dep[nxt])
        {
            if((dep[now]+1-dep[nxt])&1)if_true=true;
            continue;
        }
        dfs(nxt,now);
    }
    return;
}
inline bool cheak()
{
    if_true=false;
    for(int i=1;i<=n;i++)if(!vit[i])dfs(i,0);
    return if_true;
}

int col[N];
inline void bw(int now,int c)
{
    col[now]=c;
    for(int i=to[now].size()-1;i>=0;i--)
    {
        int nxt=to[now][i];
        if(col[nxt])continue;
        bw(nxt,3-c);
    }
    return;
}

int d_1[N];
int d_2[N];
int t_1,t_2;
int tail=0;
inline void work()
{
    t_1=t_2=0;
    for(int i=1;i<=n;i++)if(!col[i])bw(i,1);
    for(int i=1;i<=n;i++)
    {
        if(col[i]==1)
        {
            for(;t_1&&a[d_1[t_1]]<a[i]&&(tail=a[d_1[t_1]]);t_1--)printf("b ");
            d_1[++t_1]=i;printf("a ");
            continue;
        }
        for(;t_1&&a[d_1[t_1]]==tail+1&&(tail=a[d_1[t_1]]);t_1--)printf("b ");
        for(;t_2&&a[d_2[t_2]]<a[i]&&(tail=a[d_2[t_2]]);t_2--)printf("d ");
        d_2[++t_2]=i;printf("c ");
    }
    for(;t_1||t_2;)
    {
        if(t_2&&((!t_1)||(a[d_2[t_2]]<a[d_1[t_1]]))){printf("d ");t_2--;}
        else {printf("b ");t_1--;}
    }
    printf("\n");
    return;
}
int main()
{
    int i,j;
    n=rin();
    for(i=1;i<=n;i++)a[i]=rin();
    s[n+1]=0x3f3f3f3f;
    for(i=n;i>=1;i--)s[i]=min(s[i+1],a[i]);
    for(i=1;i<=n;i++)for(j=i+1;j<=n;j++)if(a[i]<a[j]&&a[i]>s[j])add(i,j);
    if(cheak()){puts("0");return 0;}
    work();
    return 0;
}