zoj 2672

zoj 2672


#include <stdio.h>
#include <string.h>
#define MAXN 3010
#define Inf  10000
#define Prime  24971
#define HashSize ( 1 << 20 )
using namespace std;

typedef short int  Integer;


int     N , Num [MAXN] , Ans [MAXN] , Len , Left [MAXN];
Integer MaxLong [MAXN] [MAXN] , * S [MAXN];

struct  TNode {
        int   Key , Next;
        Integer Long;
};

int     Hash [HashSize];
TNode   Node [MAXN];

bool    init ();
void    solve ();
void    print ();
Integer *   find ( int );
Integer *   Insert ( int );

main ()
{
     bool    first = true;
     while ( init () ) {
           if ( first ) first = false; else printf ( "\n" );
           solve ();
           print ();
     }
}

Integer * Insert ( int K )
{
        int p = K & ( HashSize - 1 ) , q;
        for ( q = Hash [p]; q != -1; q = Node [q].Next ) if ( Node [q].Key == K ) return & Node [q].Long;
        Node [Len].Key = K , Node [Len].Next = Hash [p] , Hash [p] = Len ++;
        return & Node [Len - 1].Long;
}

Integer * find ( int K )
{
        int p = K & ( HashSize - 1 ) , q;
        for ( q = Hash [p]; q != -1; q = Node [q].Next ) if ( Node [q].Key == K ) return & Node [q].Long;
        return NULL;
}

void solve ()
{
     if ( N < 3 ) return;

     int  i , j;
     Integer * p;
     Len = 0;
     memset ( Hash , 0xff , sizeof ( Hash ));

     for ( i = 0; i < N; i ++ ) {
         for ( j = i - 1; j >= 0; j -- ) if ( Num [i] == Num [j] ) break;
         Left [i] = j;
     }
     for ( i = 0; i < N; i ++ ) for ( j = i + 1; j < N; j ++ ) MaxLong [i] [j] = 2;

     for ( i = 0; i + 1 < N; i ++ ) {
         for ( j = 0; j + 1 < i; j ++ ) *S [j] = 0;
         if ( i ) S [i - 1] = Insert ( Num [i - 1] ) , * S [i - 1] = 0;
         for ( j = 0; j < i; j ++ )
             if ( MaxLong [j] [i] > *S [j] ) *S [j] = MaxLong [j] [i];

         for ( j = i + 1; j < N; j ++ ) {
             if ( Num [i] && Left [j] > i ) continue;
             p = find ( Num [j] - Num [i] );
             MaxLong [i] [j] = ( p == NULL ? 2 : *p + 1 );
         }
     }
}

bool init ()
{
     if ( scanf ( "%d" , &N ) == EOF ) return false;
     for ( int i = 0; i < N; i ++ ) scanf ( "%d" , &Num [i] );
     return true;
}

void print ()
{
     if ( N < 3 ) {
          printf ( "%d\n" , N );
          for ( int i = 0; i < N; i ++ ) {
              if ( i ) printf ( " " );
              printf ( "%d" , Num [i] );
          }
          return;
     }
     int  a = 0 , b = 1 , l;
     for ( int i = 0; i < N; i ++ )
         for ( int j = i + 1; j < N; j ++ ) if ( MaxLong [i] [j] > MaxLong [a] [b] ) a = i , b = j;

     l = MaxLong [a] [b];

     printf ( "%d\n" , l );
     Ans [l - 1] = Num [b] , Ans [l - 2] = Num [a];
     for ( int i = l - 3; i >= 0; i -- ) Ans [i] = Ans [i + 2] - Ans [i + 1];
     for ( int i = 0; i < l; i ++ ) {
         if ( i ) printf ( " " );
         printf ( "%d" , Ans [i] );
     }
     printf ( "\n" );
}
/*
24
1 2 3 5 -1 2 1 3 4 7 11 0 11 11 22 7 29 36 65 0 1 2 3 4
18
-1 0 -1 1 -1 1 -1 2 8 3 13 5 21 8 0 13 9 21
*/


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值