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): 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.
 

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值