hdu 4923 Room and Moor
给出一个序列 每一位上只能是0或者1 然后给出另外一个同等位数的序列B 求每一位上数字差的平方的和
使得这个和最小 且序列B上的数字要满足非递减
可以对序列A进行预处理 删除前面连续的0和后面连续的1 对中间的序列进行处理
将形如1111000的序列看作一个区间 所以序列A就可以分为几个区间
对每个区间进行求平均值(就是区间中1的个数除以区间长度)(这个值就是满足条件的B序列中的值)
因为B序列中要满足非递减情况 所以求得一个区间中的平均值后要与前面区间的平均值进行比较 如果不比前面的小就可以将该区间的值压入栈中 否则就将栈顶弹出 两个区间求平均值 再与前面的进行比较 直到比前面的大
最后对栈中保存的区间进行求值
不知道为什么之前写的那个老是WA 我也是醉了 就重新写了
写的过程中注意判断条件 与或的优先级以及rate大小比较时与eps比较的关系
代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <stack>
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 100010
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define FOV(i,a,b) for(int i=a;i>=b;i--)
#define REP(i,a,b) for(int i=a;i<b;i++)
#define REV(i,a,b) for(int i=a-1;i>=b;i--)
#define MEM(a,x) memset(a,x,sizeof a)
#define ll __int64
using namespace std;
int a[MAXN];
struct seq
{
int l,r,num;
double rate;
};
stack<seq> s;
int main()
{
freopen("ceshi.txt","r",stdin);
int tc;
scanf("%d",&tc);
while(tc--)
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int x=0,y=n-1;
while(a[x]==0) x++;
while(a[y]==1) y--;
// cout<<"y"<<y<<endl;
seq temp;
for(int i=x;i<=y;i++)
{
if(i==x||i>x&&a[i-1]==0&&a[i]==1)
{
temp.l=i;
temp.num=0;
}
if(i<y&&a[i]==0&&a[i+1]==1||i==y)
{
temp.r=i;
// cout<<"lll"<<temp.l<<"rrr"<<temp.r<<endl;
temp.rate=(temp.num*1.0)/((temp.r-temp.l+1)*1.0);
// cout<<"rrr"<<temp.rate<<endl;
while(1)
{
if(s.empty()||s.top().rate-temp.rate<eps)
{
s.push(temp);
break;
}
if(s.top().rate-temp.rate>eps)
{
temp.l=s.top().l;
temp.num+=s.top().num;
temp.rate=(temp.num*1.0)/((temp.r-temp.l+1)*1.0);
s.pop();
}
}
}
if(a[i]==1) temp.num++;
}
double ans=0.0;
while(!s.empty())
{
temp=s.top();
ans+=(1.0*(1-temp.rate)*(1-temp.rate)*temp.num+1.0*temp.rate*temp.rate*(temp.r-temp.l+1-temp.num));
s.pop();
}
printf("%.6f\n",ans);
}
return 0;
}