hdu 4923 Room and Moor [ 找规律 + 单调栈 ]

传送门

Room and Moor

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1288    Accepted Submission(s): 416

Problem Description

PM Room defines a sequence A = {A1, A2,..., AN}, each of which is either 0 or 1. In order to beat him, programmer Moor has to construct another sequence B = {B1, B2,... , BN} of the same length, which satisfies that:

Input

The input consists of multiple test cases. The number of test cases T(T<=100) occurs in the first line of input.

For each test case:
The first line contains a single integer N (1<=N<=100000), which denotes the length of A and B.
The second line consists of N integers, where the ith denotes Ai.

Output

Output the minimal f (A, B) when B is optimal and round it to 6 decimals.

Sample Input

4
9
1 1 1 1 1 0 0 1 1
9
1 1 0 0 1 1 1 1 1
4
0 0 1 1
4
0 1 1 1

Sample Output

1.428571
1.000000
0.000000
0.000000

Author

BUPT

Source

2014 Multi-University Training Contest 6

Recommend

We have carefully selected several similar problems for you:  5189 5184 5181 5180 5177

又一道G++ T,C++ AC 的好题!!!!

题意及题解转自:

http://blog.csdn.net/a601025382s/article/details/38423069

题意:

给定一个长度为n的,由0和1组成的序列ai,求一个序列bi,使得∑(bi-ai)^2最小。其中0<=bi<=1,bi<=b(i+1),bi为浮点型。输出最小的∑(bi-ai)^2的值。

题解:

对于ai序列中,开头的连续0,和结尾的连续1可以省略,因为bi中必定可以赋值连续0和连续1相同的值,使得(bi-ai)^2=0;

对于剩余的序列,我们可以分组,每组为连续1+连续0的形式(例如110010可以分成1100和10)。

对于每个组中的数ai,他们对应的bi必定是相同的。证:假设0对应的bi确定,那么要使∑(bi-ai)^2最小,1对应的bi肯定等于0对应bi中的最小值;同理1对应的bi确定时也一样。之后我们可以发现,这个值正好是rate=num1/(num1+num0),numi表示i的个数。

之后我们遍历每个分组,将每个组压入栈中。在压入栈之前,我们需要判断rate是否呈递增的,若是呈递增的,那么直接要入栈中,因为我们可以两个分组取不同的rate;若不是呈递增,那么我们需要将最后一个组出栈,然后合并,因为我们要保证bi的呈递增的;然后判断这个新的组入栈是否能是栈呈递增,不能则重复前面的动作,直到呈递增或者栈为空为止,之后将新的组压入栈中。

最后得到一个递增的栈,我们直到了每个分组的rate值,那么就能求∑(bi-ai)^2了。

13197281 2015-03-21 16:21:03 Accepted 4923 1638MS 2408K 2440 B C++ czy
13197275 2015-03-21 16:20:38 Time Limit Exceeded 4923 6000MS 2468K 2440 B G++ czy
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <stack>
  4 #include <vector>
  5 #include <algorithm>
  6
  7 #define ll long long
  8 int const N = 100005;
  9 int const M = 205;
 10 int const inf = 1000000000;
 11 ll const mod = 1000000007;
 12
 13 using namespace std;
 14
 15 int n;
 16 double ans;
 17 int aa[N];
 18 int a[N];
 19 int tot;
 20 ll qcnt1[N];
 21 ll qcnt[N];
 22 int T;
 23
 24 void ini()
 25 {
 26     ans=0;
 27     tot=0;
 28     int i,j;
 29     int st,en;
 30     scanf("%d",&n);
 31     for(i=1;i<=n;i++){
 32         scanf("%d",&aa[i]);
 33     }
 34     st=1;
 35     while(st<=n){
 36         if(aa[st]==0){
 37             st++;
 38         }
 39         else{
 40             break;
 41         }
 42     }
 43     if(st==n+1) return;
 44     en=n;
 45     while(en>st){
 46         if(aa[en]==1){
 47             en--;
 48         }
 49         else{
 50             break;
 51         }
 52     }
 53     j=0;
 54     for(i=st;i<=en;i++){
 55         j++;
 56         a[j]=aa[i];
 57     }
 58     tot=j;
 59     //printf(" tot=%d\n",tot);
 60 }
 61
 62 void solve()
 63 {
 64     int r;
 65     r=0;
 66     ll cnt1,cnt0;
 67     ll cnt;
 68     int i;
 69     int now=1;
 70     cnt1=cnt0=0;
 71     for(i=1;i<=tot;i++){
 72         if(now==1){
 73             if(a[i]==1){
 74                 cnt1++;
 75             }
 76             else{
 77                 cnt0++;
 78                 now=0;
 79             }
 80         }
 81         else{
 82             if(a[i]==0){
 83                 cnt0++;
 84             }
 85             else{
 86                 now=1;
 87                 cnt=cnt0+cnt1;
 88                 while(r!=0 && qcnt1[r]*cnt > qcnt[r]*cnt1 ){
 89                     cnt1+=qcnt1[r];
 90                     cnt+=qcnt[r];
 91                     r--;
 92                 }
 93                 r++;
 94                 qcnt1[r]=cnt1;
 95                 qcnt[r]=cnt;
 96                 cnt0=0;
 97                 cnt1=1;
 98             }
 99         }
100     }
101     if(now==0){
102         cnt=cnt0+cnt1;
103         while(r!=0 && qcnt1[r]*cnt > qcnt[r]*cnt1 ){
104             cnt1+=qcnt1[r];
105             cnt+=qcnt[r];
106             r--;
107         }
108         r++;
109         qcnt1[r]=cnt1;
110         qcnt[r]=cnt;
111     }
112     double te;
113     //printf("  r=%d\n",r);
114     while(r!=0){
115         te=1.0*qcnt1[r]/qcnt[r];
116         ans+=(1-te)*(1-te)*qcnt1[r]+te*te*(qcnt[r]-qcnt1[r]);
117         r--;
118     }
119 }
120
121 void out()
122 {
123     printf("%.6f\n",ans);
124 }
125
126 int main()
127 {
128     //freopen("data.in","r",stdin);
129     scanf("%d",&T);
130    // for(cnt=1;cnt<=T;cnt++)
131     while(T--)
132     //while(scanf("%d",&n)!=EOF)
133     {
134         ini();
135         solve();
136         out();
137     }
138 }
时间: 2024-08-01 15:21:25

hdu 4923 Room and Moor [ 找规律 + 单调栈 ]的相关文章

hdu 4923 Room and Moor (单调栈+思维)

题意: 给一个0和1组成的序列a,要构造一个同样长度的序列b.b要满足非严格单调,且 值为0到1的实数.最后使得  sum((ai-bi)^2)最小. 算法: 首先a序列开始的连续0和末尾的连续1是可以不考虑的.因为只要b序列对应开头为0. 末尾为1,既不影响单调性又能使对应的(ai-bi)^2=0. 然后, 先找111100.11100.10这样以1开始以0结束的序列块.每一块对应的b值相等且均为 这一块的平均值,即1的个数/0和1的总个数. 但是要满足b的单调性,则我们用栈来维护,如果后面一

HDU 4923 Room and Moor (多校第六场C题) 单调栈

Problem Description PM Room defines a sequence A = {A1, A2,..., AN}, each of which is either 0 or 1. In order to beat him, programmer Moor has to construct another sequence B = {B1, B2,... , BN} of the same length, which satisfies that: Input The inp

HDU 4923 Room and Moor

Problem Description PM Room defines a sequence A = {A1, A2,..., AN}, each of which is either 0 or 1. In order to beat him, programmer Moor has to construct another sequence B = {B1, B2,... , BN} of the same length, which satisfies that: Input The inp

HDU 4923 Room and Moor(瞎搞题)

瞎搞题啊.找出1 1 0 0这种序列,然后存起来,这种情况下最好的选择是1的个数除以这段的总和.然后从前向后扫一遍,变扫边进行合并.每次合并,合并的是他的前驱.这样到最后从t-1找出的那条链就是最后满足条件的数的大小. Room and Moor Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 307    Accepted Su

hdu 4923 Room and Moor(数学题)2014多校训练第6场

Room and Moor                                                                          Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Problem Description PM Room defines a sequence A = {A1, A2,..., AN}, each of

HDU 4923 Room and Moor(推理+栈维护)

HDU 4924 Room and Moor 题目链接 题意:给定一个01组成的a序列,要求一个b序列,b序列每个数值为[0, 1]之间的数,并且b序列为非递减序列,要求∑(ai?bi)2最小,求这个最小值 思路:推理,很容易看出,开头一段的0和末尾一段的1等于没有,然后中间每段类似111000这样1在前,0在后的序列,都可以列出一个公式,很容易推出选择的x为共同的一个值,为1的个数/(1的个数+0的个数)a,那么问题就变成要维护一个递增的x,利用一个栈去做维护,如果遇到一个位置递减了,那么就把

HDU 4923 Room and Moor【栈】【想法】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4923 题目大意:给你一串A = {A1, A2,..., AN}由{0,1}组成, 你要构造出一字符串 B = {B1, B2,... , BN}与A的长度相同. 求出这个最小值. 最开始见到这个题目先是想了想应该怎么做,比如先把A串处理一下. 1)把A前面的0去掉 2)把A后面的1去掉 3)将每部分的特值算出来. 举个栗子吧,字符串A将前的0去掉,后面的1去掉之后,字符串可以简化为N个 {1..

HDU 4572 Bottles Arrangement(找规律,仔细读题)

题目 //找规律,123321123321123321…发现这样排列恰好可以错开 // 其中注意题中数据范围: M是行,N是列,3 <= N < 2×M //则猜测:m,m,m-1,m-1,m-2,m-2,……,2,2,1,1求出前m个数字的和就是答案. //发现案例符合(之前的代码第二天发现案例都跑不对,真不知道我当时眼睛怎么了) #include <iostream> #include<stdio.h> #include<string.h> #inclu

HDU 4923 Room and Moor 贪心+栈

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4923 题意:,Bi可以是小数. 思路:很机智的想法,对于连续M个1+N个0的一块来说,最优解一定是,Bi=M/(M+N),因为Bi是递增的(可以手推),所以如果出现在后面的一块中的Bi>前面一块的Bi,那么就不可能取到最优解,所以将两块合并一起处理,这样过程中就需要用栈来维护了. 代码: #include <iostream> #include <cstdio> #include &