1812. 【提高组NOIP2008】双栈排序 (twostack.pas/c/cpp)

时间:2020-12-12 20:45:26

1812. 【提高组NOIP2008】双栈排序 (twostack.pas/c/cpp)

Tom最近在研究一个有趣的排序问题。如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序。

操作a

如果输入序列不为空,将第一个元素压入栈S1

操作b

如果栈S1不为空,将S1栈顶元素弹出至输出序列

操作c

如果输入序列不为空,将第一个元素压入栈S2

操作d

如果栈S2不为空,将S2栈顶元素弹出至输出序列

如果一个1~n的排列P可以通过一系列操作使得输出序列为1,2,…,(n-1),n,Tom就称P是一个“可双栈排序排列”。例如(1,3,2,4)就是一个“可双栈排序序列”,而(2,3,4,1)不是。下图描述了一个将(1,3,2,4)排序的操作序列:

当然,这样的操作序列有可能有几个,对于上例(1,3,2,4),是另外一个可行的操作序列。Tom希望知道其中字典序最小的操作序列是什么。

输入

输入文件twostack.in的第一行是一个整数n。

第二行有n个用空格隔开的正整数,构成一个1~n的排列。

输出

输出文件twostack.out共一行,如果输入的排列不是“可双栈排序排列”,输出数字0;否则输出字典序最小的操作序列,每两个操作之间用空格隔开,行尾没有空格。

样例输入

【输入输出样例1】

4

1 3 2 4

【输入输出样例2】

4

2 3 4 1

【输入输出样例3】

3

2 3 1

样例输出

【输入输出样例1】

a b a a b b a b

【输入输出样例2】

0

【输入输出样例3】

a c a b b d

数据范围限制

【限制】

30%的数据满足: n<=10

50%的数据满足: n<=50

100%的数据满足: n<=1000

一道蛮坑的题目。。。。。

比赛思路:乱打。(三个样例没过)

期望得分:

(最高):100

(最低):0

结果出来,

9.1分。呵呵哒…….

转入正题

正解:玄学之二分图染色

具体操作

(1)连边。如果a[k] < a[i] < a[j]且i< j< k,将i与j连边;

(连边的意思是不可以在同一个栈里)

方法:记录一下b[i,j](i后有没有a[j]),o(2n^2)解决;

(2)入栈:先记录c[i](代表a[i]的状态,0*,1在1栈,2在2栈)如果c[i]=0,c[i]入1栈并将于c[i]连边的点入2栈。

Warning:给出一组数据:

(if c[i]=0 then)

10

10 2 8 1 7 9 3 4 5 6

2-8,8-9,7-9连边

i=1时,10入1栈;

i=2时,2入1栈,8入2栈;

i=3时,8已经在2栈,7入1栈,2不用入1栈(已入);

i=4时,1入1栈;

i=5时,7入1栈(?),9入2栈!

但,8与9不能进一个栈!

难道输出0?

不对,7可以入2栈,那么9入1栈,成立。

这种”*“入2栈的例子,要判断。

设要入栈的点为i,i的连边点有j。

if c[j]=1 then i入2栈。

如果i入2栈都不行,输出0.

if c[i]=1 then 将i的所有连边点j,c[j]=2;

if c[i]=2 then 将i的所有连边点j,c[j]=1;

(3)出栈。

t=0;

inc(t);if c[t]=0 then break;(if c[t]=1 then s:=s+’b ’ ;if c[t]=2 then s:=s+’d ‘;)

就这样,直到t>=n,退出程序。

做完了。

注意:

1:连双向边;

2:细节!

3:那些字符要用s储存,不要直接输出。

4:字典序时,可能a操作比d先,要判断。(否则90.9)

代码:

请勿抄袭:(6293 bytes)

var
        f:array[1..100000,1..2] of longint;
        x,y:array[0..10000] of longint;
        a,q:array[1..10000] of longint;
        b:array[1..1000,1..1000] of longint;
        c,d:array[1..100000] of longint;
        i,j,k,m,n,o,p,l,s1,t,min:longint;
        bz:boolean;
        zu:array[1..1000,1..1000] of boolean;
        g:array[0..10000] of boolean;
        s:ansistring;
procedure insert(x,y:longint);
begin
        inc(t);
        f[t,1]:=y;
        f[t,2]:=q[x];
        q[x]:=t;
end;
begin
        assign(input,'twostack.in');reset(input);
        assign(output,'twostack.out');rewrite(output);
        readln(n);
        for i:=1 to n do read(a[i]);
        for i:=1 to n do begin
                min:=maxlongint;
                for j:=i+1 to n do
                        if a[j]<min then begin
                                min:=a[j];
                        end;
                if min=maxlongint then continue;
                for j:=min+1 to n do b[i,j]:=1;
                for j:=1 to min do b[i,j]:=0;
        end;
        fillchar(zu,sizeof(zu),true);
        fillchar(g,sizeof(g),true);
        for i:=1 to n do begin
                for j:=i+1 to n do begin
                        if a[i]<a[j] then begin
                                if b[j,a[i]]=1 then begin
                                        insert(a[i],a[j]);
                                        writeln(a[i],' ',a[j]);
                                        zu[a[i],a[j]]:=false;zu[a[j],a[i]]:=false;
                                end;
                        end;
                end;
        end;
        s1:=1;  t:=0;
        for i:=1 to n do begin
                if g[i]=false then continue;
                if c[a[i]]=0 then begin
                        d[a[i]]:=x[0];
                        k:=q[a[i]];
                        bz:=true;
                        while k<>0 do begin
                                if c[f[k,1]]=1 then begin
                                        bz:=false;
                                end;
                                if bz=false then break;
                                k:=f[k,2];
                        end;
                        k:=q[a[i]];
                        if bz=true then begin
                                s:=s+'a ';
                                inc(x[0]);
                                x[x[0]]:=a[i];c[a[i]]:=1;
                                while k<>0 do begin
                                        if c[f[k,1]]=0 then begin
                                                inc(y[0]);
                                                y[y[0]]:=f[k,1];
                                                c[f[k,1]]:=2;
                                                d[a[i]]:=y[0];
                                        end;
                                        k:=f[k,2];
                                end;
                        end else begin
                                s:=s+'c ';
                                inc(y[0]);
                                y[y[0]]:=a[i];c[a[i]]:=2;
                                while k<>0 do begin
                                        if c[f[k,1]]=0 then begin
                                                inc(x[0]);
                                                x[x[0]]:=f[k,1];
                                                c[f[k,1]]:=1;
                                        end;
                                        k:=f[k,2];
                                end;
                        end;
                end else if c[a[i]]=1 then begin
                        s:=s+'a ';
                        k:=q[a[i]];
                        while k<>0 do begin
                                if c[f[k,1]]=1 then begin
                                        writeln(0);
                                        close(input);close(output);
                                        halt;
                                end;
                                if c[f[k,1]]=0 then begin
                                        inc(y[0]);
                                        y[y[0]]:=f[k,1];
                                        c[f[k,1]]:=2;
                                        //s:=s+'c ';
                                end;
                                k:=f[k,2];
                        end;
                end else begin
                        k:=q[a[i]];
                        s:=s+'c ';
                        while k<>0 do begin
                                if c[f[k,1]]=2 then begin
                                        writeln(0);
                                        close(input);close(output);
                                        halt;
                                end;
                                if c[f[k,1]]=0 then begin
                                        inc(x[0]);
                                        x[x[0]]:=f[k,1];
                                        c[f[k,1]]:=1;
                                        //s:=s+'a ';
                                end;
                                k:=f[k,2];
                        end;
                end;
                t:=s1;
                j:=s1;
                repeat
                        if j=0 then continue;
                        if c[j]<>0 then begin
                                if c[j]=1 then begin
                                        s:=s+'b ';
                                        inc(j);
                                        dec(x[0]);
                                end
                                else begin
                                        if x[0]=0 then begin
                                                s:=s+'a ';
                                                inc(x[0]);x[x[0]]:=a[i+1];c[i+1]:=1; g[i+1]:=false;
                                                s:=s+'d ';

                                        end else s:=s+'d ';
                                        inc(j);
                                end;
                        end;
                        if c[j]=0 then begin
                                t:=j;
                                break;
                        end;
                until j>n;
                s1:=t;
                //writeln(s);
        end;
        writeln(s);
        close(input);close(output);
end.