bzoj5090 组题

题目

好久好久没有更新博客了,现在开始要好好学了。

分数规划第一题吧,第一次听说这个东西是在冬令营,现在算是做过一道题了吧。

二分最后的答案,之后把原数组每个数都减去这个答案,如果这个解成立的话,必须有一段区间和为正数,这样的话,我们把它转化为前缀和,只要找一个 sum[j]>=sum[i] 就好了。

但是,这道题有一个问题,就是答案要求是分数,这样我们只能求出一个小数。我们就要在判断的时候记录一下,最后输出的时候再化简就好了。

#include<bits/stdc++.h>
#define N 100000
using namespace std;
long long n,k,ansl,ansr,q,p,t;
long long a[N+5];
double l,r,mid;
double sum[N+5];
inline char nc()
{
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline long long read()
{
    long long x=0,b=1;
    char c=nc();
    for(;!(c<='9'&&c>='0');c=nc())if(c=='-')b=-1;
    for(;c<='9'&&c>='0';c=nc())x=x*10+c-'0';
    return x*b;
}
inline bool judge(double x)
{
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i]*1.0-x;
    int pos=0;
    for(int i=k;i<=n;i++)
    {
        if(sum[i]>=sum[pos])
        {
            ansl=pos+1,ansr=i;
            return true;
        }
        if(sum[i-k+1]<sum[pos])pos=i-k+1;
    }
    return false;   
}
inline long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
    freopen("in.txt","r",stdin);
    n=read(),k=read();
    for(int i=1;i<=n;i++)a[i]=read();
    l=r=a[1];
    for(int i=2;i<=n;i++)l=min(l,a[i]*1.0),r=max(r,a[i]*1.0);
    for(int i=1;i<=50;i++)
    {
        mid=(l+r)/2.0;
        if(judge(mid))l=mid;
        else r=mid;
    }
    q=ansr-ansl+1;
    for(int i=ansl;i<=ansr;i++)p+=a[i];
    t=gcd(abs(p),q);
    printf("%lld/%lld",p/t,q/t);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值