雙棧排序
阿新 • • 發佈:2020-12-14
感覺有一些地方沒有梳理通,需要重新考慮一遍。
一開始的建圖,是沒有問題的。
對於任意三元組 \((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\)
但是間接相連的就沒有 必定在棧內 這個性質。
這裡是可以直接由 \(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; }