[BZOJ]5090: 组题 01分数规划

Description
著名出题人小Q的备忘录上共有n道可以出的题目,按照顺序依次编号为1到n,其中第i道题目的难度系数被小Q估计为a_i,难度系数越高,题目越难,负数表示这道题目非常简单。小Q现在要出一套难题,他决定从备忘录中选取编
号连续的若干道题目,使得平均难度系数最高。当然,小Q不能做得太过分,一套题目必须至少包含k道题目,因此他不能通过直接选取难度系数最高的那道题目来组成一套题。请写一个程序,帮助小Q挑选平均难度系数最高的题
目。

题解:

感觉题解的做法好复杂啊……看到平均数就想分数规划,那么将问题转化为判定性问题。设 s[i] a[i] 的前缀和,当前二分的答案为 mid ,那么我们的目标就是找到:

s[j]s[i1]j(i1)>=mid
移项得:
s[j]j×mid(s[i1](i1)×mid)>=0
那么只要每次求出前缀和,然后再减去下标乘 mid ,找有没有 ji+1>=k s[j]s[i1]>=0 就可以了。那么怎么找呢?这个也十分简单,设 mn[i] 0 i位置的 s[i] 最小值,那么对于每个 s[i] ,找 s[mn[ik]] 就行了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const long double eps=1e-7;
const int Maxn=100010;
const int inf=2147483647;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
LL gcd(LL a,LL b){return((!b)?a:gcd(b,a%b));}
LL x,y,sum[Maxn];
int n,k,q[Maxn],mn[Maxn];
long double a[Maxn],s[Maxn],t;
bool check(long double v)
{
    s[0]=mn[0]=0;
    for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i];
    for(int i=1;i<=n;i++)s[i]-=v*(long double)(i);
    for(int i=1;i<=n;i++)
    {
        if(s[i]<s[mn[i-1]])mn[i]=i;
        else mn[i]=mn[i-1];
    }
    for(int i=k;i<=n;i++)
    if(s[i]>=s[mn[i-k]]){y=i;x=mn[i-k];return true;}
    return false;
}
int main()
{
    n=read(),k=read();sum[0]=0;
    for(int i=1;i<=n;i++)scanf("%Lf",&a[i]),sum[i]=sum[i-1]+(LL)(a[i]);
    long double l=-100000000,r=100000000;
    while(l+eps<=r)
    {
        long double mid=(l+r)/2.0;
        if(check(mid))l=mid;
        else r=mid;
    }
    l=(l+r)/2.0;int u=0;
    if(l<0)l=-l,u=1;
    LL t1,t2;
    t1=(LL)(l*(long double)(y-x)+0.5);t2=y-x;
    LL g=gcd(abs(t1),t2);
    if(u)printf("-");printf("%lld/%lld",t1/g,t2/g);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值