CF526E Transmitting Levels

题目大意:给出环上 n 个正整数。q 此询问,每次给定 L,分成尽量少的段,使每段长度和 L

n106,q50

将环展开成长度为 2n 的序列,令 nxti 表示以 i 开头同块最远端。

双指针求出后枚举起点,暴力向后跳,时间复杂度 O(n2)

fi,j 表示从 i 开始 2j 块的最远端,fi,0=nxti,通过倍增预处理。

对于每个起点倍增向后条,时间复杂度 O(qnlogn),仍不可过。

取任意起点,暴力向后跳,设原来的环被分成了 m 段,最小的一段长度 nm

枚举该段上的点类似 check,每次不长不超过 O(m)

时间复杂度 O(q×nm×m)=O(qn)

#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f3f3f3f3f
typedef long long ll;
ll n, q, L, a[2000005], nxt[2000005];
int main() {
scanf("%lld%lld", &n, &q);
for (ll i = 1; i <= n; i++) {
scanf("%lld", a + i);
a[i + n] = a[i];
}
while (q--) {
scanf("%lld", &L);
for (ll i = 1, j = 1, sum = 0; i <= 2 * n; i++) {
while (j <= 2 * n && sum + a[j] <= L)
sum += a[j++];
nxt[i] = j; sum -= a[i];
}
ll pos = 1, ans = inf;
for (ll i = 2; i <= n; i++) {
if (nxt[i] - i < nxt[pos] - pos)
pos = i;
}
for (ll s = pos + 1; s <= nxt[pos]; s++) {
ll t = s - n * (s > n), l = t, res = 0;
while (l <= t + n - 1)
res++, l = nxt[l];
ans = min(ans, res);
}
printf("%lld\n", ans);
}
return 0;
}
posted @   CodingShark  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示