牛客周赛 Round 90——真爱粉Tk(三)
题目
题解
根据题意,像这种最大值最小,最小值最大的问题,就引导我们要用二分。对于一个元素而言,我们要怎么知道他有多少个25对呢?我们可以存储2的个数,每次遇到5就可以和前面c2个2结合形成25对,所以我们可以存储下来当前元素有多少个2,多少个5,还有多少个25对,每次拼接就增加了 前面元素2的个数 * 当前元素5的个数 + 当前元素的25对数。我们可以预处理init()出每个元素这些的个数。然后进行二分查找check(),每次放不下了再新建一段,最后看看段数是否小于等于k段。
参考代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
#define int long long
int n, k;
vector<int> cnt2(N), cnt5(N), cnt25(N);
vector<string> a(N);
void init(int u) {
int c2 = 0, c5 = 0, c25 = 0;
for(auto c : a[u]) {
if(c == '2') {
c2++;
}else if(c == '5') {
c5++;
c25 += c2;
}
}
cnt2[u] = c2, cnt5[u] = c5, cnt25[u] = c25;
}
bool check(int mid) {
int sg = 1;
int tc2 = 0, c25 = 0;
for(int i = 0; i < n; i++) {
int nc25 = c25 + cnt25[i] + cnt5[i] * tc2;
int nc2 = tc2 + cnt2[i];
if(nc25 > mid) {
sg++;
tc2 = cnt2[i];
c25 = cnt25[i];
}else {
c25 = nc25;
tc2 = nc2;
}
}
return sg <= k;
}
signed main() {
cin >> n >> k;
a.resize(n);
cnt2.resize(n), cnt5.resize(n), cnt25.resize(n);
for(int i = 0; i < n; i++) {
cin >> a[i];
init(i);
}
int l = 0, r = 1e18;
while(l < r) {
int mid = l + r >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout << l << endl;
return 0;
}

浙公网安备 33010602011771号