CF803D 杂志广告

1 CF803D 杂志广告

2 题目描述

时间限制 \(1s\) | 空间限制 \(256M\)

The main city magazine offers its readers an opportunity to publish their ads. The format of the ad should be like this:

There are space-separated non-empty words of lowercase and uppercase Latin letters.

There are hyphen characters '-' in some words, their positions set word wrapping points. Word can include more than one hyphen.

It is guaranteed that there are no adjacent spaces and no adjacent hyphens. No hyphen is adjacent to space. There are no spaces and no hyphens before the first word and after the last word.

When the word is wrapped, the part of the word before hyphen and the hyphen itself stay on current line and the next part of the word is put on the next line. You can also put line break between two words, in that case the space stays on current line. Check notes for better understanding.

The ad can occupy no more that k lines and should have minimal width. The width of the ad is the maximal length of string (letters, spaces and hyphens are counted) in it.

You should write a program that will find minimal width of the ad.

数据范围:\(1 ≤ k ≤ 10^5\)

3 题解

看到最大值最小,我们很容易想到二分算法。由于字符串的长度 \(len\)\(10^6\),我们可以想到 \(O(len \times log_2 len)\) 的算法。容易想到,我们可以二分枚举 \(l\),表示当前最长的一行的长度,然后贪心验证每一个 \(l\) 是否可行。

更具体地,如果加上某个单词后长度超过了 \(l\),那么我们将总行数 \(+1\)。在最后,如果总行数大于 \(k\),那么说明当前长度肯定不合法,返回不可行,否则返回可行即可。注意到如果 \(l\) 小于最长的单词的长度,那么该长度必定不行。所以我们可以先用 \(O(len)\) 的时间复杂度找出所有的单词中最长的单词,此时二分的下限就是这个最长单词的长度。

4 代码(空格警告):

#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e6+10;
#define int long long
int k, l, r, mid, cnt, cnt1, ans, maxn;
int word[N];
string s;
bool check(int len)
{
    int cnt2 = 1, le = 0;
    for (int i = 1; i <= cnt1; i++)
    {
        le += word[i];
        if (le > len)
        {
            cnt2++;
            le = word[i];
        }
    }
    if (cnt2 > k) return 0;
    return 1;
}
signed main()
{
    cin >> k;
    getchar();
    getline(cin, s);
    for (int i = 0; i < s.length(); i++)
    {
        if (s[i] == '-' || s[i] == ' ')
        {
            word[++cnt1] = cnt+1;
            cnt = 0;
        }
        else cnt++;
    }
    if (cnt) word[++cnt1] = cnt;
    for (int i = 1; i <= cnt1; i++) maxn = max(maxn, word[i]);
    l = maxn;
    r = s.length();
    while (l <= r)
    {
        mid = (l+r)/2;
        if (check(mid)) r = mid-1, ans = mid;
        else l = mid+1;
    }
    cout << ans;
    return 0;
}

欢迎关注

posted @ 2021-04-04 17:55  David24  阅读(40)  评论(0编辑  收藏  举报