1 solutions

  • 1
    @ 2025-8-8 20:34:33

    题解 由于数据范围较大,所以使用普通枚举不能得到满分。因此考虑二分。

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    long long m,s,a[100005];//数据范围较大,使用long long 
    bool check(long long x){//二分中决定范围的check函数 ,x表示等待的时间 ,x越大,完成或者正在进行收银的人越多 
    	long long sum=0;
    	for(int i=1;i<=n;i++){//依次枚举n个收银台 
    		if(sum>m){
    			return true;//如果人数已经大于自身前面的人数,说明等待的时间过长(即x过大) 
    		}
    		sum += x/a[i];//人数等于总时间除以收银台处理的时间 
    		if (x % a[i] != 0) sum += 1;//向上取整 
    	}
    	if(sum>=m){
    		return true;
    	}
    	else return false;
    }
    int main(){
    	cin>>n;
    	for(int i=1;i<=n;i++){
    		cin>>a[i];
    	}
    	cin>>m;
        long long l=0,r=a[1]*m;//r为较大值 
        while(l+1<r){
        	long long mid=(l+r)/2;
        	if(check(mid)){
        		r=mid;//若人数大于前方人数(包括自己),则说明mid较大,应将范围缩小至(l,mid] 
    		}
    		else{
    			l=mid;//小于则反之 
    		}
    	}
    	for(int i=1;i<=n;i++){
    		s += (r-1)/a[i];//计算s秒时,完成或者正在收银的人数。(r-1)表示进入收银台前 
    		if ((r-1) % a[i] != 0) s += 1;//向上取整 
    	}
    	long long k=0;
    	for(int i=1;i<=n;i++){
    		if((r-1)%a[i]==0){//若(r-1)除以a[i]的余数为零,说明在进入收银台前第i位收银台刚好为空。 
    			k++;//由于前方可能还有人,空的收银台可以让出 
    		}
    		if(k+s==m){//当k+s=m时,说明已经到第一位并且有空的收银台 
    			cout<<i;
    			break;
    		}
    	}
    	return 0;
    }
    

    Hydro河中域第一篇题解

    Information

    ID
    3
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    4
    Tags
    # Submissions
    66
    Accepted
    7
    Uploaded By