zoukankan      html  css  js  c++  java
  • 羊圈

    题目描述
    ZYC的农场有N(1<=N<=100,000)块连续的区域排成一排,每块区域上都有确定数量的羊(每块区域不超过2000千只)。 
    现在ZYC想要将一些区域用围墙围起来,作为信息社的优秀成员,当然要给自己出点难题:他希望围起来的区域里羊的总数/区域数的值最大,并且保证围起来的区域数不小于M。 
    输入
    第一行包括两个整数,分别表示N和M 
    以下N行每行一个正整数,表示对应区域羊的数量(单位千只) 
    输出
    输出最大平均数(单位只) 
    样例输入
    10 6
    6 
    4
    2
    10
    3
    8
    5
    9
    4
    1
    样例输出
    6500

    解析:由于很明显,暴力是n*n级的算法,很明显TLE,最多只有71分,所以我就用DP优化了一下,代码如下:
    #include<bits/stdc++.h>
    using namespace std;
    struct Nd
    {
        long long x,sum; 
    };
    Nd dp[100001];
    long long a[100001];
    long long ans;
    int main()
    {
        long long n,m;
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]*=1000;
        long long sum2=0;
        for(int i=1;i<=m;i++) sum2+=a[i];
        dp[m].x=m;
        dp[m].sum=sum2;
        for(int i=m+1;i<=n;i++)
        {
            dp[i].sum=dp[i-1].sum+a[i];
            dp[i].x=dp[i-1].x+1;
            int max_n=0,max_ans,max_ans2,j_sum=0;
            for(int j=dp[i].x;j>=m;j--)
            {
                if(max_n<(dp[i].sum-j_sum)/j)
                {
                    max_n=(dp[i].sum-j_sum)/j;
                    max_ans=j;
                    max_ans2=j_sum;
                }
                j_sum+=a[i-j+1];
            }
            dp[i].sum-=max_ans2;
            dp[i].x=max_ans;
        }
        for(int i=m;i<=n;i++)
        {
            ans=max(ans,dp[i].sum/dp[i].x);
        } 
        //cout<<endl;
        cout<<ans;
        return 0;
    }
    

      很明显,这样虽然优化了一些,但还是接近n*n,所以只有79分。但这样还是不行,我就想到了二分,二分求答案。代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    const int NR=100000+5;
    int n,m;
    long long a[NR];
    long long sum[NR];
    long long sum2[NR];
    long long l=-1e6,r=1e6;//二分左右端点 
    bool check(long long x)//***核心*** check函数 
    {
        for(int i=n;i>=1;i--)
            sum2[i]=max(a[i]-x,sum2[i+1]+a[i]-x);//i往后的羊数最多比x大几 
        for(int i=1;i<=n-m+1;i++)
    	{
            if(sum[i+m-1]-sum[i-1]>=m*x)//如果取m个区域 
                return 1;
            if(sum[i+m-1]-sum[i-1]+sum2[i+m]>=x*m)//取>m个区域 
                return 1;
        }
    	return 0;
    }
    int main()
    {
        scanf("%d%d",&n,&m);//读入 
        for(int i=1;i<=n;i++)
    	{
            scanf("%lld",&a[i]);
            a[i]*=1000;
            sum[i]=sum[i-1]+a[i];
        }
        while(l<=r)//二分模板 
    	{
            int mid=(l+r)/2;
            if(check(mid)) l=mid+1;
            else r=mid-1;
        }
        cout<<r<<endl;
        return 0;
    } 
    

      

  • 相关阅读:
    Go简介
    sRGB标准与伽马校正
    【Web】HTTP基本认证之 Basic Auth
    【ElasticSearch】 ElasticSearch SQL(十三)
    【ElasticSearch】 ElasticSearch X-Pack之用户认证(十二)
    【ElasticSearch】 ElasticSearch Java客户端(十一)
    【ElasticSearch】 ElasticSearch集群分布式文档(十)
    【ElasticSearch】 ElasticSearch集群之分片、副本、故障转移(九)
    【ElasticSearch】 ElasticSearch集群安装(八)
    【ElasticSearch】 全文搜索(七)
  • 原文地址:https://www.cnblogs.com/chen-1/p/11175863.html
Copyright © 2011-2022 走看看