Room and Moor
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 553 Accepted Submission(s): 156
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
题意:求出一个非递减序列使它与A序列之差的平方和最小
首先要知道去掉前面的0和后面的1,只需要对剩下的序列进行处理就可以,把剩下的序列分成几组,每一组都是先有几个1然后几个0,如果序列是1 1 1 0 0 1 0,就分成两组,一组1 1 1 0 0,另一组1 0。
这样分好之后,YY一下,可以知道,每一组里取的最优值是num_1/(num_1+num_0)(rate),然后要将这些值非递减排列起来,用一个栈就好,如果当前值的rate大于栈顶的,直接入栈,否则将这个值出栈,与当前值合并,再判断与栈顶的rate的关系,这样就可以保证栈里都是非降序的了。
这题还有个小坑点(反正我被坑了)。。。。就是把后面的1全部去掉之后,结尾肯定是0,我们只赋值到了下标n-1,n后面的没有赋值也可能是0,所以统计0的个数就不对了。。代码也带了注释
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
const int MAXN=100010;
struct node
{
int num0,num1,id;
double ra;
}p[MAXN];
stack<node> S;
int a[MAXN];
int main()
{
int t,n,i;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
int l=0,r=n-1;
while(a[l]==0)
l++;
while(a[r]==1)
r--;
if(l>r)
{
printf("0.000000\n");
continue;
}
int id=0;
for(i=l;i<=r;)
{
int j=0,k=0;
while(a[i]==1)
{
i++;
j++;
}
while(a[i]==0&&i<n) //这里可能超出n。多统计了0
{
i++;
k++;
}
p[id].id=id;
p[id].num0=k;
p[id].num1=j;
p[id++].ra=1.0*j/(j+k);
}
for(i=0;i<id;i++)
{
if(S.empty())
S.push(p[i]);
else
{
node temp=S.top();
if(temp.ra<=p[i].ra)
{
S.push(p[i]);
continue;
}
node g=p[i];
while(1)
{
temp=S.top();
if(temp.ra>g.ra)
{
g.num0+=temp.num0;
g.num1+=temp.num1;
g.ra=1.0*g.num1/(g.num0+g.num1);
S.pop();
}
else
{
S.push(g);
break;
}
if(S.empty())
{
S.push(g);
break;
}
}
}
}
double ans=0;
while(!S.empty())
{
node temp=S.top();
S.pop();
ans+=1.0*temp.num1*(1-temp.ra)*(1-temp.ra)+1.0*temp.num0*temp.ra*temp.ra;
}
printf("%.6f\n",ans);
}
return 0;
}