ABC370 F - Cake Division
给定一个长度为
看到最小值最大,想到二分。
对于环上问题,容易想到断环成链。
因为并不需要求方案数,所以对于每个
现在我们需要快速的求解是否从某点断开后,能不能在序列上跳
看见 “跳”,想到倍增优化dp,
时间复杂度
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=(r);++i)
#define G(i,r,l) for(int i(r);i>=(l);--i)
using namespace std;
using ll = long long;
const int N = 4e5 + 1005;
int f[N][19], a[N];
ll sum[N];
int n, k, maxn;
bool ck(int l, int r, int lim){
int tot = k, nw = l;
G(i, maxn, 0){
if(nw > r) return 0;
if(tot < (1 << i) || f[nw][i] > r) continue;
tot -= (1 << i);
nw = f[nw][i] + 1;
if(!tot) break;
} return tot == 0;
}
void init(ll lim){
for(int i = 1, j = 1; i <= n; ++ i){
while(j <= 2 * n && sum[j] - sum[i - 1] < lim) ++ j;
f[i][0] = j;
f[i + n][0] = min(2 * n + 1, j + n);
}
F(j, 1, maxn) F(i, 1, n * 2) f[i][j] = f[i][j - 1] + 1 > n * 2 ? 2 * n + 1 : f[f[i][j - 1] + 1][j - 1];
}
bool check(int lim){
init(lim);
F(i, 1, n) if(ck(i, i + n - 1, lim)) return 1;
return 0;
}
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n >> k;
F(i, 1, n) cin >> a[i], a[i + n] = a[i];
F(i, 1, n * 2) sum[i] = sum[i - 1] + a[i];
maxn = __lg(2 * n);
ll l = 0, r = sum[n] + 1, mid;
while(l + 1 < r){
mid = (l + r) >> 1;
if(check(mid)) l = mid;
else r = mid;
}
int ans1 = l, ans2 = 0;
init(ans1);
F(i, 1, n) ans2 += ck(i, i + n - 1, ans1);
cout << ans1 << ' ' << n - ans2 << '\n';
return fflush(0), 0;
}
分类:
AtCoder做题记录
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】