hdu 4923 Room and Moor

本文详细解析HDU4923题目,介绍一种通过预处理序列并利用栈来优化求解的方法,实现寻找满足特定条件的序列B,使两序列间差值平方和最小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值