洛谷1404平均数

我的妈呀...真的好长时间没有去做题了,开始做啦

今天的这道题只是一个二分

但是思维很好(毕竟刘神都不会)

这道题是在看算法进阶二分的时候看到的题目,用刘神的话讲,套路啦

思维1:二分出一个答案,并且将所有的值减去该答案,然后得到一个新的序列bi如果满足条件的连续区间,其累加和一定大于或等于零

思维2:如何O(n)求出该答案是否成立,就是计算出新的序列bi的前缀和si,如果在1到i-m之间存在j使得s[i]-s[j]>=0,则答案一定成立

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
//#include<bits/stdc++.h>
using namespace std;
int n,m;
long long a[100010],b[100010],l=200000000,r=0,mid,c[100010];
bool work(long long p)
{
    c[0]=0;
    b[0]=0;
    long long Min=1ll*200000000000;
    for(int i=1;i<=n;i++)
    {
        b[i]=b[i-1]+a[i]-p;
        c[i]=min(c[i-1],b[i]);
    }
    c[0]=0;
    for(int i=n;i>=m;i--)
    {
        if(b[i]-c[i-m]>=0)return true;
    }
    return false;
    /*for(int i=1;i<=n;i++){
        b[i]=b[i-1]+a[i]-p;
        if(i>=m) Min=min(b[i-m],Min);//更新Min
        if(b[i]-Min>=0) return 1;
    }
    return 0;*/
}
int main()
{
    //freopen("xf.in","r",stdin);
    //freopen("xf.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        a[i]*=1000;
        l=min(l,a[i]);
        r=max(r,a[i]);
    }
    while(l+1<r)
    {
        mid=(l+r)>>1;
        if(work(mid))l=mid;
        else r=mid;
    }
    if(work(r))printf("%lld
",r);
    else printf("%lld
",l);
    return 0;
}

不过在开始的时候,我在不同的oj上(poj,luogu,duoxiao)都会出现一个点的WA,最后感谢刘神帮我检查出了bug,原来是我的c[0]其实

是存在意义的,不能赋值为无穷大,改为0就a掉了

原文地址:https://www.cnblogs.com/mybing/p/13554879.html