AC + WA + TLE,提交记录
WA 就算了,不知道为什么会 T?时间复杂度应该没错,并且似乎没有可以出现死循环的地方。
思路和大多数题解相同,倍增+二分,代码有注释。
// F - Cake Division
#include<bits/stdc++.h>
using namespace std;
constexpr int INF = 0x3f3f3f3f;
int main()
{
int n, K;
cin >> n >> K;
vector<int> a(n + 1), sum(2 * n + 1);
for(int i = 1; i <= n; i++)
{
cin >> a[i];
sum[i] = sum[i-1] + a[i];
}
for(int i = n + 1; i <= 2 * n; i++)
sum[i] = sum[i-1] + a[i-n];
vector<vector<int>> f(2 * n + 3);
for(auto vec: f) vec.resize(__lg(K) + 1);
auto check = [&](int x) -> int // 返回需要切开的切线的数量
{
for(int i = 1, j = 1; i <= 2 * n; i++)
{
while(j < 2 * n && sum[j] - sum[i - 1] < x) j++;
if(sum[j] - sum[i-1] >= x) f[i][0] = j + 1;
else f[i][0] = 2 * n + 2; // 相当于INF
}
f[2 * n + 2][0] = 2 * n + 2;
int t = __lg(K);
for(int k = 1; k <= t; k++)
for(int i = 1; i <= 2 * n + 2; i++)
f[i][k] = f[f[i][k-1]][k-1];
int cnt = 0; // 能作为起点的点数
for(int i = 1; i <= n; i++) // 枚举每个点,判断其是否能成为起点
{
int en = i;
for(int j = 0; (1 << j) <= K; j++)
if(K & (1 << j)) en = f[en][j];
if(en <= i + n) cnt++;
}
return cnt;
};
int l = 0, r = sum[n], ans = -1, cnt = -1;
while(l <= r)
{
int mid = (l + r) >> 1, res = check(mid);
if(res != 0) // 可行(至少有一个解)
{
l = mid + 1;
ans = mid, cnt = n - res;
}
else r = mid - 1;
}
cout << ans << ' ' << cnt << endl;
return 0;
}