題目鏈接:點擊查看
題目大意:給出一個長度為 n 的數列 a,表示每個位置的障礙物數量,現在有 m 個學生可以來搬走障礙物,每一秒鐘可以做出的行為如下:
從位置 i 移動到位置 i + 1從當前位置搬走一個障礙物
問搬走所有的障礙物最少需要多長時間
題目分析:不難看出時間越多,越有可能完成任務,所以可以二分時間然后貪心去check
最初的思想是讓學生從前向后去搬,發現不好處理,看了題解后發現可以讓學生從后向前去搬
具體思想如下,因為搬走所有的箱子所需要的時間是固定的,唯一不同的就是花費在路上的時間,同時 m 個學生可以看成是相互獨立的,每個人每次都有相同的時間
所以我們不妨枚舉每個學生的路線,讓每個學生一開始就去搬當前最后一個位置的箱子,如果搬完后還剩下了時間的話,可以直接去搬前面位置的箱子而無需花費額外的時間去移動
代碼:
?
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const LL inf=0x3f3f3f3f3f3f3f3f;const int N=1e6+100;int n,m,a[N],b[N];bool check(LL x)
{for(int i=1;i<=n;i++)b[i]=a[i];int pos=n;for(int i=1;i<=m;i++)//枚舉m個同學 {LL remain=x;//當前同學的體力while(pos>0&&!b[pos])pos--;if(pos==0)//搬完了 return true;remain-=pos;//先要到達最后這個箱子的位置while(remain>0){while(pos>0&&!b[pos])pos--;if(pos==0)return true;int mmin=min(remain,1LL*b[pos]);b[pos]-=mmin;remain-=mmin;}}while(pos>0&&!b[pos])pos--;return pos==0;
}int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",a+i);LL l=0,r=inf,ans=-1;while(l<=r){LL mid=l+r>>1;if(check(mid)){r=mid-1;ans=mid;}elsel=mid+1;}printf("%lld\n",ans);return 0;
}
?
總結
以上是生活随笔為你收集整理的CodeForces - 551C GukiZ hates Boxes(二分+贪心)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。