现在的位置: 首页 > 综合 > 正文

ZOJ 2091 Mean of Subsequence

2019年04月15日 ⁄ 综合 ⁄ 共 1798字 ⁄ 字号 评论关闭

设i开头的子序列中,产生最小平均值的序列结尾下标为x[i]。

那么考虑x[i]确定之后的情况。a[i-1]如果比(i,x[i])的平均值小,那么x[i-1] = i-1。反之如果大于(i,x[i]),那么显然应把x[i]赋值于x[i-1]。

但是仍然有问题。考虑10,2,3,2的情况。设下标为1-4。x[4] = 4,x[3]=4,x[2]=2,x[1]=2。但是实际情况中,x[1]=4。为何?因为除了(2,2)能降低1的平均值外,(3,4)也能降低1开头序列的平均值。而且很容易得到如(2,2)(3,4)这样的一个阶梯型上升队列(j,x[j]),只要比较a[i-1]和(j,x[j])的平均值就可以判断是否需要继续迭代。

 

#include <cstdio>
#include 
<string>

int N, a[10001], sum[10001], x[10001];
double d[10001];

void init ();
void dp ();
void print ();
void pt ();

int main ()
{
    freopen ( 
"in.txt""r", stdin );
    
while ( scanf ( "%d"&N ) == 1 )
    
{
        
int i;
        
for ( i = 1; i <= N; i ++ )
            scanf ( 
"%d"&a[i] );
        init ();
        dp ();
        pt ();
        print ();
    }

    
return 0;
}


void init ()
{
    
int i, t = 0;
    sum[
0= t;
    
for ( i = 1; i <= N; i ++ )
    
{
        t 
+= a[i];
        sum[i] 
= t;
    }

}


void dp ()
{
    
int i, j, k;
    x[N] 
= N, d[N] = double ( a[N] );
    
for ( i = N - 1; i >= 1; i -- )
    
{
        
double dmin = double ( a[i] );
        x[i] 
= i, j = i + 1, k = x[j];
        
while ( j <= N )
        
{
            
double t = double ( sum[k] ) - double ( sum[j - 1] );
            t 
/= k - j + 1;
            
if ( t > a[i] )
                
break;
            
else
            
{
                t 
= double ( sum[k] ) - double ( sum[i - 1] );
                t 
/= k - i + 1;
                
if ( t < dmin )
                    x[i] 
= k, dmin = t;
                j 
= k + 1, k = x[j];
            }

        }

        d[i] 
= dmin;
    }

}


void print ()
{
    
double ave = 1e-10;
    
int i;
    
for ( i = 1; i <= N; i ++ )
        
if ( d[i] > ave )
            ave 
= d[i];    
    printf ( 
"%.6f ", ave );
}


void pt ()
{
    
int i, j;
    i 
= 1, j = x[i];
    
while ( i <= N )
    
{
        printf ( 
"%.6f ", d[i] );
        i 
= j + 1, j = x[i];
    }

    printf ( 
" " );
}

抱歉!评论已关闭.