• 【noip2008】双栈排序


    题解:

    对于任意一对ij (i<j) 如果存在k (k>j) 使得a[k]<a[i]<a[j] ij连线

    表示ij不能在同一个栈

    连完后对这个图做二分图染色 如果不能染色则无解

    染完色后若颜色为0就表示该点会放在第一个栈 否则在第二个栈

    知道每个点在哪个栈后 就能直接模拟了- -

     

    证明:

    命题:对于任意一对ij (i<j) 如果存在k (k>j) 使得a[k]<a[i]<a[j],是ij不在同一个栈的充分必要条件

    所谓充分必要条件就是

    若满足命题则ij必不能在一个栈 且若不满足命题 ij能在同一个栈

     

    先证明若满足命题则ij必不能在一个栈:

    因为弹出顺序要有序 所以 当j要进栈时i还没出栈(因为有a[k]<a[i] k还没出栈 )

    a[i]<a[j] 所以这时j不能进栈

     

    再证明若不满足命题 ij能在同一个栈:

    不满足命题有两种情况

    1.不存在i<j a[i]<a[j]

    2.对任意ijk (i<j<k) a[j]<a[i] 且 a[j]<a[k]

     

    情况这是个降序序列 显然能放进同一个栈

    情况j要进栈时 显然i已经被弹出或能被弹出了 因为j后面没有比a[i]小的数

          所以i不会对j产生影响

    代码:

     1 #include <cstdio>
     2 #include <cstdlib>
     3 const int N=1001,M=2000001;
     4 struct inli{
     5     int next,data;
     6     inli(const int a=0,const int b=0):
     7         next(a),data(b){}
     8 }line[M];
     9 int n,a[N],col[N],son[N],sta1[N],sta2[N],top1,top2,last[N],nl;
    10 void makeline(){
    11     for (int i=1;i<=n;i++){
    12         int k=i;
    13         for (int j=i+1;j<=n;j++)
    14         if (a[j]<a[i]) k=j;
    15         last[i]=k;
    16         for (int j=i+1;j<k;j++)
    17         if (a[j]>a[i]){
    18             line[++nl]=inli(son[i],j),son[i]=nl;
    19             line[++nl]=inli(son[j],i),son[j]=nl;
    20         }
    21     }
    22 }
    23 void print(){
    24     puts("0");
    25     exit(0);
    26 }
    27 void search(int t){
    28     for (int i=son[t];i;i=line[i].next)
    29     if (!col[line[i].data]){
    30         col[line[i].data]=-col[t];
    31         search(line[i].data);
    32     }else if (col[t]==col[line[i].data])
    33     print();
    34 }
    35 void makecol(){
    36     for (int i=1;i<=n;i++)
    37     if (!col[i]){
    38         col[i]=1;
    39         search(i);
    40     }
    41 }
    42 void push1(int t){
    43     printf("a ");
    44     sta1[++top1]=t;
    45 }
    46 void pop1(){
    47     printf("b ");
    48     --top1;
    49 }
    50 void push2(int t){
    51     printf("c ");
    52     sta2[++top2]=t;
    53 }
    54 void pop2(){
    55     printf("d ");
    56     --top2;
    57 }
    58 void work(){
    59     for (int i=1;i<=n;i++)
    60     if (col[i]==1){
    61         while (top1 && a[sta1[top1]]<a[i]) pop1();
    62         push1(i);
    63     }else{
    64         while (top1 && last[sta1[top1]]<i) pop1();
    65         while (top2 && a[sta2[top2]]<a[i]) pop2();
    66         push2(i);
    67     }
    68     while (top1 || top2){
    69         if (!top1) pop2();
    70         else if (!top2) pop1();
    71         else if (a[sta1[top1]]<a[sta2[top2]]) pop1();
    72         else pop2();
    73     }
    74 }
    75 int main(){
    76     scanf("%d",&n);
    77     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    78     makeline();
    79     makecol();
    80     work();
    81     puts("");
    82 }
    View Code
  • 相关阅读:
    我cnblogs的主题
    Scala Error: error while loading Suite, Scala signature Suite has wrong version expected: 5.0 found: 4.1 in Suite.class
    Spark之路 --- Scala用JFreeChart画图表实例
    Spark之路 --- Scala IDE Maven配置(使用开源中国的Maven库)和使用
    Spark之路 --- Windows Scala 开发环境安装配置
    epoll函数
    Linux网络编程目录
    函数wait和waitpid
    会话
    进程组
  • 原文地址:https://www.cnblogs.com/g-word/p/3385182.html
Copyright © 2020-2023  润新知