感觉之前的*1900好简单
题意:
思路:
注意到宽度具有单调性,考虑二分宽度
然后限制了最大宽度,要使行数 <= k
那么在check里贪心,每行选的尽可能多
考虑双指针,每次选长度为mid的区间,然后如果右端点 r 没有指向换行符,那么 r 指向左边离它最近的换行符
所以需要预处理一个位置左边离它最近的换行符的位置
这样就做完了
Code:
#include <bits/stdc++.h>
using i64 = long long;
const int N = 1e6 + 10;
std::string s, s2;
int k, len = 0, ns;
int pre[N];
std::string substr(int l, int r) {
return s.substr(l, r - l + 1);
}
bool check(int mid) {
std::vector<std::string> res;
int l = 1, r = 1;
while(1) {
if (l > ns || r > ns) break;
while(r <= ns && r - l + 1 < mid) r ++;
if (r == ns + 1) r --;
if (s[r] != ' ' && s[r] != '-' && r != ns) r = pre[r];
if (l > r) return false;
res.push_back(substr(l, r));
l = r + 1;
r = l;
}
return res.size() <= k;
}
void solve() {
std::cin >> k;
getline(std::cin, s2);
getline(std::cin, s);
ns = s.size();
s = " " + s;
s = s + " ";
for (int i = 1; i <= ns; i ++) {
if (s[i] == '-' || s[i] == ' ') {
pre[i] = i;
}else {
pre[i] = pre[i - 1];
}
}
//std::cout << check(7) << "\n";
int l = 1, r = ns;
int ans = 0;
while(l <= r) {
int mid = l + r >> 1;
if (check(mid)) {
ans = mid;
r = mid - 1;
}else {
l = mid + 1;
}
}
std::cout << ans << "\n";
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t = 1;
while (t--) {
solve();
}
return 0;
}