hdu 4923 数学和单调栈

题目:

hdu 4923 数学和单调栈_第1张图片

我们可以将开头的0和末尾的1直接忽略,因为他们不会造成对最后结果造成影响,而中间的每组11.....111 00......000一定是给定的形式,而要使当前组的平方差之和最小,那么每组的b定是一个一个值,且当且仅当这个值是平均值时,才会最小,通过单调栈维护单调性,如果出现不符合的情况,那么就将不符合的逐一合并到符合要求为止,依旧是利用每组的平均值,因为上式是形容一堆点的变化幅度,因为当前点已经给定,所以针对于平均值这条直线,他们的变化幅度是最小的

代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#define MAX 100007

using namespace std;

int t,n;
int num[MAX];

struct Node
{
    int num0 , num1 ; double  aver;
}node[MAX] ;

int main ( )
{
    scanf ( "%d" , &t );
    while ( t-- )
    {
        scanf ( "%d" , &n );
        for ( int i = 1; i <= n ; i++ ) scanf ( "%d" , &num[i] );
        int cnt = 0 , id = 1 , rid = n;
        while ( id <= n && num[id] == 0 ) id++;
        while ( rid >= id && num[rid] == 1 ) rid--;
        if ( rid <= id ) 
        {
            puts ( "0.000000" );
            continue;
        }
        int flag = 0;
        node[0].num0 = 0 , node[0].num1 = 0;
        for ( int i = id ; i <= rid ; i++)
        {
            if ( num[i] == 0 && flag == 0 ) flag = 1;
            if ( (num[i] == 1 && flag == 1)) 
            {
                flag = 0;
                node[cnt].aver =node[cnt]. num1 *1.0 / (node[cnt].num0 + node[cnt].num1) ;
                cnt++;
                node[cnt].num0 = node[cnt].num1 = 0;
            }
            if ( num[i] ) node[cnt].num1++;
            else node[cnt].num0++;
        }
        node[cnt].aver =node[cnt]. num1 *1.0 / (node[cnt].num0 + node[cnt].num1 );
        cnt++;
        stack<Node> s;
        s.push ( node[0]  );
        for ( int i = 1 ; i < cnt ; i++ )
        {
            if ( s.empty() ||  node[i].aver >= s.top().aver )
                s.push ( node[i]  );
            else 
            {
                Node temp = s.top();
                while ( temp.aver > node[i].aver )
                {
                    node[i].num1 += temp.num1;
                    node[i].num0 += temp.num0;
                    node[i].aver = node[i].num1*1.0/
                        (node[i].num0+node[i].num1);
                    s.pop();
                    if ( s.empty() ) break;
                    temp = s.top ();
                }
                s.push ( node[i] );
            }
        }
        double ans = 0.0;
        while ( !s.empty ())
        {
            Node temp = s.top();
            ans += ( 1 - temp.aver )* ( 1 - temp.aver )*temp.num1
                   + temp.aver * temp.aver*temp.num0;
            s.pop(); 
        }
        printf ( "%.6f\n" , ans );    
    }
}


你可能感兴趣的:(数据结构,C++,算法,数学,单调栈)