[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;
}
posted @ 2023-09-10 16:39  l-cacherr  阅读(44)  评论(0编辑  收藏  举报