hdu4923 Room and Moor
4923Room and Moor
Room and MoorTime 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 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: 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 Source
Recommend
hujie
|
题意:输入由1和0组成的A序列,求一个长度与A序列相同的、在实数[0,1]之间的不下降序列B,使得sum of (Ai-Bi)^2最小,输出这个最小的sum。
题解:
先观察一下,发现最左边的0和最右边的1可以忽视,因为我们可以把B左边这段当做0,B右边那段当1。解下来看剩下的。
假如有一段是1111.....00000,由x个1和y个0组成,则这一段最优的B是x/(x+y),也就是平均值,这可以通过样例看出。
而如果有两段这样的段,111...000 111....000,我们计算两段分别的平均值,若左段小于等于右段,则左段用左段的平均值,右段用右段的平均值是最优的;若左段大于右段,则不能各用各的平均值了,我们把这两段合作一段,用一起的平均值。
根据这个思想,我们把下降的段都合并了,得到平均值上升的若干段,各用各的平均值,哇,最优解!
合并时,从头到尾,相邻的组平均值比较。有可能会出现合并完这两个,新组平均值比再前一个组的平均值还小的情况,所以我们每次合并,都要和之前的比较一发,保证队列不下降。
代码:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
#include<stack>
#include<queue>
using namespace std;
#define ll __int64
#define usint unsigned int
#define mz(array) memset(array, 0, sizeof(array))
#define minf(array) memset(array, 0x3f, sizeof(array))
#define REP(i,n) for(int i=0;i<(n);i++)
#define FOR(i,x,n) for(int i=(x);i<=(n);i++)
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define WN(x) printf("%d\n",x);
#define RE freopen("D.in","r",stdin)
#define WE freopen("1.out","w",stdout) const int maxn=; struct pig {///分组,每个pig记录一组的和与长度
int sum,len;
pig(int s,int l) {
sum=s;
len=l;
}
pig() {}
long double ave() {///还能算平均值,怕不怕
return sum*1.0/len;
}
}; pig v[maxn];
int vl,vr;
int n;
bool a[maxn]; int main() {
int i,T,j;
int l,r;
int sum,len;
long double ans;
int flag;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
for(i=; i<n; i++)
scanf("%d",&a[i]);
l=;
r=n;
while(a[l]==&&l<n)l++;///去除左边的0
while(a[r-]==&&r>=)r--;///去除右边的1
sum=0.0;
flag=;
len=;
vl=;
vr=;
for(i=l; i<r; i++) {///将剩下的分成若干组不上升序列,记录各组的和与长度
//cout<<i<<'.'<<sum<<'/'<<len<<endl;
if(a[i]==) {
if(flag==)
sum++,len++;
else if(flag==) {
v[vr++]=(pig(sum,len));
sum=a[i];
len=;
flag=;
}
} else if(a[i]==) {
len++;
if(flag==)
flag=;
}
}
if(len>) v[vr++]=pig(sum,len);///把最后剩下的一组也加入
for(i=vl+; i<vr; i++) {
if(v[i-].ave()>v[i].ave()) {///若相邻两组平均值呈下降,则合并为一组
v[i].sum+=v[i-].sum;
v[i].len+=v[i-].len;
v[i-].sum=;
v[i-].len=;
for(j=i-; j>=; j--)
if(v[j].len>) {
if(v[j].ave()>v[i].ave()) {///有可能合并完后小于更之前的平均值,若发生这种事,则把之前的也合并进来
v[i].sum+=v[j].sum;
v[i].len+=v[j].len;
v[j].sum=;
v[j].len=;
}
else break;
}
}
}
while(v[vl].len== && vl<vr) vl++;///去除开头的空组
// printf("vl=%d,vr=%d:",vl,vr);
// for(i=vl;i<vr;i++)
// printf("%.6f,%d ",v[i].sum,v[i].len);
// puts("");
ans=0.0;
for(i=vl; i<vr; i++) {
if(v[i].len!=) {///若为非空组,则统计len*(1-ave)^2+(len-sum)*ave^2
//cout<<v[i].sum<<','<<v[i].len<<','<<(double)v[i].ave()<<endl;
//cout<<(long double)ave<<','<<(long double)ave2<<','<<(long double)(len-v[i].sum)<<endl;
if(v[i].len>) ans+=( v[i].ave() * v[i].ave() ) * (v[i].len-v[i].sum) + (1.0-v[i].ave())*(1.0-v[i].ave()) * v[i].sum;
//cout<<ans<<endl;
}
}
printf("%.6f\n",(double)ans);
}
return ;
}
hdu4923 Room and Moor的更多相关文章
- 【HDU】4923 Room and Moor(2014多校第六场1003)
Room and Moor Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) ...
- 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. ...
- HDOJ 4923 Room and Moor
用一个栈维护b的值,每次把一个数放到栈顶. 看栈首的值是不是大于这个数,假设大于的话将栈顶2个元素合并.b的值就是这两个栈顶元素的平均值. .. Room and Moor Time Limit: 1 ...
- HDU 4923 Room and Moor(推理+栈维护)
HDU 4924 Room and Moor 题目链接 题意:给定一个01组成的a序列.要求一个b序列,b序列每一个数值为[0, 1]之间的数,而且b序列为非递减序列,要求∑(ai−bi)2最小,求这 ...
- hdu 4923 Room and Moor [ 找规律 + 单调栈 ]
传送门 Room and Moor Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Oth ...
- HDU 4923 Room and Moor(瞎搞题)
瞎搞题啊.找出1 1 0 0这样的序列,然后存起来,这样的情况下最好的选择是1的个数除以这段的总和. 然后从前向后扫一遍.变扫边进行合并.每次合并.合并的是他的前驱.这样到最后从t-1找出的那条链就是 ...
- HDU 4923 Room and Moor (单调栈)
题意: 给你一个A数列,让你求一个单调递增的B数列(0<=bi<=1),使得sum{(ai-bi)^2}最小. 思路: 很明显,如果A = 0...01...1,那么bi=ai即可. 可以 ...
- 写一个TODO App学习Flutter本地存储工具Moor
写一个TODO App学习Flutter本地存储工具Moor Flutter的数据库存储, 官方文档: https://flutter.dev/docs/cookbook/persistence/sq ...
- HDU 4923 Room and Moor
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4923 解题报告:给出一个长度为n的只包含0和1的序列,是否存在一个序列Bi满足一下条件: 1. ...
随机推荐
- 【bzoj3674】 可持久化并查集加强版
http://www.lydsy.com/JudgeOnline/problem.php?id=3674 (题目链接) 题意 维护并查集3个操作:合并:回到完成第k个操作后的状态:查询. Soluti ...
- UVA11426 欧拉函数
大白书P125 #include <iostream> #include <cstring> using namespace std; #define MMX 4000010 ...
- Java replace & replaceAll
Java字符串中需要对一些字符进行替换,用到最多的是replace和replaceAll两个方法.这两个方法在使用的时候需要注意: replace: public String replace (Ch ...
- 数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树
一.简述 二叉树的遍历主要是先序.中序.后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些.二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具! 此外,非递归所用的栈 ...
- 数据结构算法C语言实现(九)--- 拓展:由迷宫问题引申的AI贪吃蛇
一.简述 [开发中]由于期末时间有限,而且要用到后面的最短路径(可能),所以打算小学期在实现这一部分
- [JavaEE]如何唤醒Sleep中的线程
主线程调用子线程的interrupt()方法,导致子线程抛出InterruptedException, 在子线程中catch这个Exception,不做任何事即可从Sleep状态唤醒线程,继续执行. ...
- 用DOS命令打开IE浏览器、我的文档等等
用DOS命令打开IE浏览器 在“start”-运行中直接输入网址就可以了.如输入百度: http://www.baidu.com Command:[ start http://www.baidu.c ...
- maven工程直接部署在tomcat上
http://www.cnblogs.com/guodefu909/p/4874549.html (现在用的是第三点.)
- javamail实践
public static void main(String[] args) throws Exception, Exception { MimeMessage message=new MimeMes ...
- HTML 速查列表
HTML 基本文档 <!DOCTYPE html> <html> <head> <title>文档标题</title> </head& ...
