题目:
https://www.luogu.org/problem/show?pid=1155
好题!
第一眼以为是水题;
码完,交上;
于是……红蓝绿……
贪心做法只有40分;
错误之处:字典序并非最优,或会出现无解情况;
正解:
对于2,3,1这组数,2和3显然不能都放在一个栈中;
类似的数满足:
i < j < k , a[k] < a[i] < a[j] , 此时, a[i] 和 a[j] 需要放到两个栈中;
于是考虑二分图染色,然后模拟;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=2000001;
int dp[MAXN],fst[MAXN],nxt[MAXN],col[MAXN],a[MAXN];
int stack1[MAXN],stack2[MAXN];
int n,tot,top1,top2,num,now=1;
char ans[MAXN];
bool flag;
struct hh {int from,to;}ma[MAXN];
void build(int f,int t)
{
ma[++tot]=(hh){f,t};
nxt[tot]=fst[f];
fst[f]=tot;
return;
}
void dfs(int x,int c)
{
col[x]=c;
for(int i=fst[x];i;i=nxt[i])
{
int v=ma[i].to;
if(col[v]==-1) dfs(v,c^1);
else if(col[v]==col[x]) { flag=1;return; }
}
return;
}
void pop()
{
while(true)
{
if(top1 && stack1[top1]==now)
{
ans[++num]='b';
top1--,now++;
}
else if(top2 && stack2[top2]==now)
{
ans[++num]='d';
top2--,now++;
}
else break;
}
return;
}
void init()
{
memset(dp,0x7f,sizeof(dp));
memset(col,-1,sizeof(col));
return;
}
void solve()
{
init();
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
dp[i]=min(dp[i],a[j]);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(a[i]<a[j] && a[i]>dp[j])
build(i,j),build(j,i);
for(int i=1;i<=n;i++)
if(!flag && col[i]==-1) dfs(i,1);
if(flag) {puts("0\n");return;}
for(int i=1;i<=n;i++)
{
if(col[i] & 1)
stack1[++top1]=a[i],ans[++num]='a';
else
stack2[++top2]=a[i],ans[++num]='c';
pop();
}
for(int i=1;i<=num;i++) cout<<ans[i]<<" ";
return;
}
int main()
{
solve();
return 0;
}