[noip2008]双栈排序

题解。。。网上都有

注意:

①为了找到i<j<k 且a[k]<a[i]<a[j]这样的k,只需用DP求出某个数后面最小的数即可

②染色的是点的下标,所以在栈中存数的时候存a[i]

③因为每次都是给原序列中的数先染1后染2,所以答案是字典序最小的

program tt;
type point=record
      y,next:longint;
end;
var aim,l,i,n,la,lb,j:longint;
    f,sa,sb,a,head,color:array[1..1000]of longint;
    edge:array[1..2000]of point;
function min(a,b:longint):longint;
begin
 if a<b then min:=a else min:=b;
end;
procedure add(x,y:longint);
begin
 l:=l+1;
 edge[l].y:=y;
 edge[l].next:=head[x];
 head[x]:=l;
 l:=l+1;
 edge[l].y:=x;
 edge[l].next:=head[y];
 head[y]:=l;
end;
procedure dfs(x,c:longint);
var p:longint;
begin
 color[x]:=c;
 p:=head[x];
 while p<>-1 do
  begin
   if color[edge[p].y]=c then    //冲突
    begin
     writeln(0);
     halt;
    end;
   if color[edge[p].y]=0 then dfs(edge[p].y,3-c);//1,2两染色
   p:=edge[p].next;
  end;
end;
begin
 read(n);
 for i:=1 to n do head[i]:=-1;
 for i:=1 to n do read(a[i]);
 f[n+1]:=maxlongint;
 for i:=n downto 1 do   //DP,只要找它后面的最小的数就可以了
  f[i]:=min(f[i+1],a[i]);
 for i:=1 to n-1 do
  for j:=i+1 to n do
   if (a[i]<a[j])and(f[j+1]<a[i]) then
    add(i,j);
 //染色
 for i:=1 to n do
  if color[i]=0 then
   dfs(i,1);

   
 la:=0;lb:=0;
 aim:=1;  //还要判断当前是否为要输出的那个数,不是就还要入栈
 for i:=1 to n do
  begin
   if color[i]=1 then
    begin
     write('a',' ');
     la:=la+1;
     sa[la]:=a[i];
    end
   else
    begin
     write('c',' ');
     lb:=lb+1;
     sb[lb]:=a[i];
    end;
   while (la>0)and(sa[la]=aim)or(lb>0)and(sb[lb]=aim) do
    begin
     if (la>0)and(sa[la]=aim) then
      begin
       write('b',' ');
       la:=la-1;
      end
     else
      begin
       write('d',' ');
       lb:=lb-1;
      end;
     aim:=aim+1;
    end;
  end;
end.


 

你可能感兴趣的:(noip)