[ABC319D] Minimum Width 题解
[ABC319D] Minimum Width 题解
题意分析
给定 \(n\) 个单词,现在想像“记事本”一样把它们依次地一行一行显示出来。每个字母宽度为一,单词之间需要有空格,宽度也为一。一个单词不可以成两部分显示在两行。如果单词最后一个字母来到行末,直接换行,不用空格。
给定窗口最大高度 \(E\) ,求窗口最小宽度 \(L\)。
思路
根据朴素的生活经验,随着 \(L\) 的增大,\(E\) 非严格单调递减。于是我们可以二分 \(L\),然后解决。
为什么是单调的呢?因为如果一行越宽,那么这一行可能容纳的单词数量就越多。那么总行数就一定是会持平于当前或者变少的。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 5;
LL n,m,a[N];
LL check(LL width)
{
LL cnt = 1;
LL idx = 0;
for(int i = 1;i <= n;i++)
{
if(width < a[i])
return 1e18;
if(idx + a[i] + 1 <= width)
{
idx += a[i] + 1;
}
else if(idx + a[i] == width)
{
idx += a[i];
cnt++;
idx = 0;
}
else
{
cnt++;
idx = a[i] + 1;
}
}
if(idx == 0) cnt--;
return cnt;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n >> m;
for(int i = 1;i <= n;i++)
{
cin >> a[i];
}
LL l=0,r=1e18,mid;
while(l < r)
{
mid = (l + r) / 2ll;
LL res = check(mid);
if(res > m)
l = mid+1ll;
else if(res <= m)
r = mid;
}
cout << l << "\n";
return 0;
}