Room and Moor
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1016 Accepted Submission(s): 321
Problem Description
PM Room defines a sequence A = {A
1, A
2,..., A
N}, each of which is either 0 or 1. In order to beat him, programmer Moor has to construct another sequence B = {B
1, B
2,... , B
N} 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 A i.
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 A i.
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
题意:相当于构造一个bi满足如上条件并使等式最小。其实没那么复杂,想想还是太烂了。b序列从0到1,所以a序列的前置的0和后置的1都可以不要,只要中间部分。从1开始,变成0也不会改变b的值,所以1,0为一个区间,1,0为1个区间的去计算区间的平均值。平均值必定是最优保持最小的。(求导可知)。然后我们把第i个区间跟第i-1个区间进行比较如果后者平均值大于等于前者则没问题,b正好可以满足,否则则合并这两个区间计算新的平均值继续往前面区间比较,直到满足或者前面没有区间了。这个我们可以用栈进行存储区间并弹出区间。最后求出栈里面每个区间的最小值就是最优解了。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <list>
#include <vector>
#define LL __int64
#define EPS 1e-8
using namespace std;
struct node
{
int x,y;//分别一个10区间代表1的个数,0的个数,和平均值
double z;
}f[50010];
int main()
{
int T,i,k,n;
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
int t=0,flag=1;
memset(f,0,sizeof(f));
for (i=1;i<=n;i++)
{
scanf("%d",&k);
if (t==0 && k==0) continue;
if (k==1)
{
if (flag==1)
{
if (t!=0) f[t].z=(f[t].x*1.0)/(f[t].x+f[t].y);
t++;
flag=0;
}
f[t].x++;
}
else
{
flag=1;
f[t].y++;
}
}
if (k==1) t-=1;
else f[t].z=(f[t].x*1.0)/(f[t].x+f[t].y);
stack<node>st;
for (i=1;i<=t;i++)
{
while (!st.empty())
{
node s=st.top();
if (f[i].z-s.z>=EPS)
{
st.push(f[i]);
break;
}
else
{
f[i].x+=s.x;
f[i].y+=s.y;
f[i].z=(f[i].x*1.0)/(f[i].x+f[i].y);
st.pop();
}
}
if (st.empty()) st.push(f[i]);
}
double ans=0.0;
while (!st.empty())
{
node s=st.top();
st.pop();
ans+=pow(1-s.z,2)*s.x*1.0+pow(s.z,2)*s.y*1.0;
}
printf("%.6lf\n",ans);
}
return 0;
}