题解 CF551C 【GukiZ hates Boxes】
这一道题目的考点为二分答案 + 模拟
二分答案我换成了是倍增,因为蒟蒻我怕二分答案写错(害怕二分写错的同学可以跟我一起写倍增啊)。
模拟的时候有一个技巧,就是每次记录一下当前所有物品中第一个没有被搬完的坐标点。
然后大力模拟。
这道题一定要开longlong,写倍增的时初始答案一定要足够大(最好开满longlong),我这里到了1e17才过。
Code:
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
int a[100005],b[100005];
long long ans = 10000110000000000;
int Tw[62] = {1} ;
int F[100005] , R = 0;
int pd(int x)
{
int flag = 0,nxt = 1;
for(int i = 1 ; i <= n ; i ++)
{
b[i] = a[i];
if(b[i] == 0)flag ++;
}
for(int i = 1 ; i <= m && flag != n; i ++)
{
int life = x;
life -= F[nxt];
while(b[F[nxt]] <= life && life > 0 && flag < n)
{
flag ++,life -= b[F[nxt]],nxt ++;
life -= (F[nxt] - F[nxt - 1]);
}
if(b[F[nxt]] > life && life > 0){
b[F[nxt]] -= life;
continue;
}
}
if(flag == n)return 1;
return 0;
}
void get_ans()
{
for(int i = 62 ; i >= 0 ; i --)
if(ans > Tw[i] && pd(ans - Tw[i]) != 0)ans -= Tw[i];
cout << ans << endl;
}
signed main()
{
cin >> n >> m;
for(int i = 1 ; i <= n ; i ++)
{
cin >> a[i];
if(a[i] != 0)R ++ , F[R] = i;
}
for(int i = 1 ; i <= 62 ; i ++)
Tw[i] = Tw[i-1] << 1;
get_ans();
return 0;
}
By MYCui