zoukankan      html  css  js  c++  java
  • hdu4923 f(A,B)分段处理

    题意:
           给你序列A,让你构造序列B然后求出最小的f(A <B),其中A 是0,或者1组成的,而B是[0,1]的实数,f(A,B) = 求和(i从1到n) (Ai - Bi)^ 2.


    思路:
          首先有一点很明确,那就是我们可以消除面连续的0,和后面连续的1,一开始我的想法是直接求中间部分的平均数, 然后就前面的连续0不用管,后面的连续1不用管,然后中间的部分就是平均数,结果妥妥的WA了,其实正解是分段处理,分成这样的 111000,10
    ,1110,1111100000...就是断成一些连续1加连续0组成的小段,然后对于当前的这一段的最优就是当前这段的平均数,但是有一点要注意,题目要求的是非递减顺序,那么如果当前的这一段的平均数比前面的那一段的小,我们就得把一段和上一段合并,合并之后如果还比上上一段小,那么在合并(这个地方可以用一个栈,比较方便写),最后在根据剩下的段数来计算答案,既保证了最小,有保证了上升。



    #include<stdio.h>
    #include<string.h>
    #include<stack>
    
    using namespace std;
    
    typedef struct
    {
       double s0 ,s1;
    }NODE;
    
    int num[110000];
    NODE node[110000];
    
    int main ()
    {
       int n ,t ,i ,s11 ,mk;
       scanf("%d" ,&t);
       while(t--)
       {
          scanf("%d" ,&n);
          for(s11 = 0 ,i = 1 ;i <= n ;i ++)
          {
             scanf("%d" ,&num[i]);
             if(num[i]) s11 ++;
          }
          for(mk = n + 1 ,i = 1 ;i <= n ;i ++)
          if(num[i]) {mk = i;break;}
          if(s11 == n || mk == n + 1)
          {
             puts("0.000000");
             continue;
          }
          int tt = 0;
          double s1 = 0 ,s0 = 0;
          num[n+1] = 1;
          for(i = mk ;i <= n ;i ++)
          {
             if(num[i]) s1 ++;
             else s0 ++;
             if(!num[i] && num[i+1])
             {
                node[++tt].s1 = s1;
                node[tt].s0 = s0;
                s1 = s0 = 0;
             }
          }
          stack<NODE>st;
          NODE xin ,tou;
          for(i = 1 ;i <= tt ;i ++)
          {
             if(st.empty())
             {
                st.push(node[i]);
                continue;
             }
             xin = node[i];
             tou = st.top();
             double tp = tou.s1 / (tou.s1 + tou.s0);
             double xp = xin.s1 / (xin.s1 + xin.s0);
             if(xp < tp)
             {
                while(1)
                {
                   tou = st.top();
                   st.pop();
                   xin.s1 += tou.s1;
                   xin.s0 += tou.s0;
                   if(st.empty())
                   {
                      st.push(xin);
                      break;
                   }
                   tou = st.top();
                   tp = tou.s1 / (tou.s1 + tou.s0);
                   xp = xin.s1 / (xin.s1 + xin.s0);
                   if(xp >= tp)
                   {
                      st.push(xin);
                      break;
                   }
                }
             }
             else st.push(node[i]);
          }
          double ans = 0;
          while(!st.empty())
          {
             NODE tou = st.top();
             st.pop();
             double tp = tou.s1 / (tou.s1 + tou.s0);
             ans += (1 - tp) * (1 - tp) * tou.s1 + tp * tp * tou.s0;
          }
          printf("%.6lf
    " ,ans);
       }
       return 0;
    }
            

  • 相关阅读:
    华科机考:特殊排序
    华科机考:排序
    华科机考:字符串连接
    华科机考:a+b
    华科机考:IP地址
    华科机考:统计单词
    iOS 应用评分
    jQuery Custom PopUp Window
    Csharp:字符串操作
    Css:Conditional comments 条件注释
  • 原文地址:https://www.cnblogs.com/csnd/p/12062882.html
Copyright © 2011-2022 走看看