zoukankan      html  css  js  c++  java
  • 暑假考试题1:Dinner(二分+贪心)

    题意:

    一共N个人坐在坐在圆桌旁,服务员拿来了M份菜单。第i个人阅读菜单并点出自己喜欢的菜需要花费时间T[i]。 当一个人点完菜之后,就会把菜单传到他右手边的第一个人。 M份菜单是同时发出的,每个菜单只能同时被一个人阅读。 希望知道如何分发菜单,才能让点餐的总时间花费最少呢?

    n<=5e4,m<=3e3

    分析:

    1.求的是最小值,考虑二分

    2.圆桌说明是环,处理环的方法:复制序列+枚举断点

    所以:二分一个答案mid,check的时候枚举以每一个点作为开头,依次向后传菜单能否满足mid(依次向后传,时间超了就菜单++)

    那么总复杂度为n*n*logn

    考虑优化:

    1.真的需要枚举每一个点做开头吗?

    eg:1 3 2 6 7   明显,如果mid=7,那么应该这样划分:1 3 2 / 6 / 7

    然后会发现,枚举从1开始,和从4开始,从5开始,是等价的划分方法。

    所以说,只需要划分到前缀和刚好大于mid的位置2,就足够了

    2.每一次传菜单的时候一定要一个一个传吗?

    我们希望快速找到一个位置,刚好传到它就超时了,那么可以通过二分找这个位置:记录前缀和,lower_bound确定位置

    最后复杂度:n*logn*logn

    #include<bits/stdc++.h>
    using namespace std;
    #define N 50005
    int n,m,a[N],sum[N*2],bn;
    bool work(int now,int x,int nx)
    {
        int cnt=0;
        while(now<=nx){
            int pos=upper_bound(sum+1,sum+n*2,sum[now-1]+x)-sum;//优化2 
            if(now==pos) pos++;
            cnt++; now=pos;
            if(cnt>m) return false;
        }
        return true;
    }
    bool check(int x)
    {
        int xx=lower_bound(sum+1,sum+n*2,x)-sum;//优化1
        for(int i=1;i<=xx;i++){
            if(work(i,x,n+i-1)) return true; 
        }
        return false;
    }
    int main()
    {
        freopen("dinner.in","r",stdin);
        freopen("dinner.out","w",stdout);
        int maxn=0,minn=0,ans=0;
        scanf("%d%d",&n,&m);
        bn=n;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            minn=max(a[i],minn);
            maxn+=a[i];
            sum[i]=sum[i-1]+a[i];
        } 
        for(int i=1;i<=n;i++)
        sum[n+i-1]=sum[n]+sum[i-1];
        int l=minn,r=maxn;
        while(l<r){
            int mid=(l+r)>>1;
            if(check(mid)) ans=mid,r=mid;
            else l=mid+1;
        }
        printf("%d
    ",ans);
    }
    /*
    4 2 
    1 2 3 4
    ans 5
    3 2 
    1 5 10
    
    */
  • 相关阅读:
    ClickHouse 监控及备份 (三)ClickHouse 配置
    ClickHouse 监控及备份 (二)Prometheus&Grafana 的安装
    ClickHouse 监控及备份 (一)ClickHouse 监控概述
    ClickHouse 高级(八)运维(1)常见问题排查
    ClickHouse 高级(七)MaterializeMySQL 引擎
    ClickHouse 高级(六)物化视图
    使用Iperf调整网络
    WinForm中DataGridView的使用(四)
    数据库设计经验总结
    WinForm使用Label控件模拟分割线(竖向)
  • 原文地址:https://www.cnblogs.com/mowanying/p/11396454.html
Copyright © 2011-2022 走看看