1 条题解

  • 0
    @ 2021-8-21 17:07:53
    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+5,M=1e3+5;
    int n,m,k,x;
    int a[N],rnd[M];
    int ans=1e9;
    void init() //看起来玄学的优化 
    {
    	//注意到当最小值是x=m-1取到时
    	//当前的做法会TLE
    	//所以考虑随机化枚举的过程
    	//枚举次数O(m)->O(ln(m)) 
    	for(int i=0;i<m;++i)
            rnd[i]=i;
        random_shuffle(rnd,rnd+m);
    }
    inline int mod(int v){return v<m?v:v-m;}
    bool calc(int limit)
    {
    	//sum可以最开始就超过limit
    	//这样就可以实现在每分一组令总数+1
    	//就不用再加尾判 
    	int sum=limit+1,tot=0;
    	for(int i=1;i<=n;++i)
    	{
    		int val=mod(a[i]+x);
    		if(val>limit)
                return 0;
            sum+=val;
    		if(sum>limit)
    		    sum=val,++tot;
    	}
    	return tot<=k;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;++i)
            scanf("%d",&a[i]);
        //发现不能直接计算x和最终结果关系 
        //注意到0<=x<m<=1000,所以考虑暴力枚举x 
        init();
        //求最大值的最小值 
    	//所以考虑二分答案 
    	for(int k=0;k<m;++k)
    	{
    		x=rnd[k];
    		int l=0,r=ans-1;
    		//优化程度巨大的剪枝
    		//先判断它有没有可能成为更优解 
    		if(!calc(r)) continue;
    		while(l<=r)
    		{
    			int mid=(l+r)>>1;
    			if(calc(mid))
    			    r=mid-1,ans=mid;
    			else
    			    l=mid+1;
    		}
    	}
    	printf("%d",ans);
    	return 0;
    }
    
    
    • 1

    信息

    ID
    460
    时间
    2000ms
    内存
    256MiB
    难度
    6
    标签
    递交数
    37
    已通过
    11
    上传者