Average UVA - 1451 斜率优化

题意:给定长度为N的01串,选一个长度不小于L的区间,使得子串中,数字的平均值最大。如果有多解,区间尽量小,如果任然有多解,起点下边尽量小。

首先求出前缀和a[i],为前n项数字和。区间i-j的平均值即为(a[j]-a[i-1])/(j-i+1);算法思路,从小到大枚举t,找出t'<=l,并且满足斜率t't最大。

中间重点在求t'时,需要维护一个凹区间,凹区间具有斜率递增的性质,因此可以再插入一个新的节点时,将区间内新形成的凸加点删除。然后在凹区间内找到与t斜率最大的一个点,更新结果。

 

#include<bits/stdc++.h>
using namespace std;
double a[100010];
double p[100010];
char s[100010];
int cmp(int x1,int x2,int x3,int x4)
{
      return (a[x1]-a[x2-1])*(x3-x4+1)-(a[x3]-a[x4-1])*(x1-x2+1);
}
int main()
{
    int t;
    scanf("%d",&t);
    int n,L;
    while(t--)
    {
        scanf("%d%d%s",&n,&L,s);
        int len=n;
        for(int i=1;i<=len;i++)
            a[i]=a[i-1]+s[i-1]-'0';
        int l=1,r=L;
        int i=0,j=0;
        for(int t=L;t<=len;t ++) {//从小到大枚举t,找到t'<=t-L并斜率最大
            while(j-i>1&&cmp(t-L,p[j-2],t-L,p[j-1])>=0) j--; //删除上凸的点,被删除的在右边连续
            p[j++]=t-L+1; //增加新元素
            while(j-i>1&&cmp(t,p[i+1],t,p[i])>=0) i++; //确定新的切点,因为切点的x坐标一定是不断增加的
            int c=cmp(r,l,t,p[i]);
            if(c<0||c==0&&(r-l)>(t-p[i])) {
                l=p[i];r=t ;
            }
        }
        printf("%d %d\n",l,r);

    }
    return 0;
}

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值