【二分】数列分段 Section II

mac2024-05-29  32

L i n k Link Link

l u o g u luogu luogu P 1182 P1182 P1182

D e s c r i p t i o n Description Description

对于给定的一个长度为N的正整数数列 A − i A−i Ai,现要将其分成 M ( M ≤ N ) M(M≤N) M(MN)段,并要求每段连续,且每段和的最大值最小。

关于最大值最小:

例如一数列 42451 4 2 4 5 1 42451要分成 3 3 3

将其如下分段:

[ 4 [4 [4 2 ] [ 4 2][4 2][4 5 ] [ 1 ] 5][1] 5][1]

第一段和为 6 6 6,第 2 2 2段和为 9 9 9,第 3 3 3段和为 1 1 1,和最大值为 9 9 9

将其如下分段:

[ 4 ] [ 2 [4][2 [4][2 4 ] [ 5 4][5 4][5 1 ] 1] 1]

第一段和为 4 4 4,第 2 2 2段和为 6 6 6,第 3 3 3段和为 6 6 6,和最大值为 6 6 6

并且无论如何分段,最大值不会小于 6 6 6

所以可以得到要将数列 42451 4 2 4 5 1 42451要分成 3 3 3段,每段和的最大值最小为 6 6 6

I n p u t Input Input

第1行包含两个正整数 N , M N,M NM

第2行包含 N N N个空格隔开的非负整数 A i A_i Ai ,含义如题目所述。

O u t p u t Output Output

一个正整数,即每段和最大值最小为多少。

S a m p l e Sample Sample I n p u t Input Input

5 3 4 2 4 5 1

S a m p l e Sample Sample O u t p u t Output Output

6

H i n t Hint Hint

对于 20 20% 20的数据,有 N ≤ 10 N≤10 N10

对于 40 40% 40的数据,有 N ≤ 1000 N≤1000 N1000

对于 100 100% 100的数据,有 N ≤ 100000 , M ≤ N , A i 之 和 不 超 过 1 0 9 N≤100000,M≤N, A_i之和不超过10^9 N100000,MN,Ai109

T r a i n Train Train o f of of T h o u g h t Thought Thought

这题我用二分来做 因为要涉及到区间和,所以,前缀和优化,然后二分答案 具体看代码

C o d e Code Code

#include<iostream> #include<cstdio> int n, m, sum[100005]; using namespace std; bool check(int mid) { int end = 1, start = 0, cnt = m; while (cnt--) { while (sum[end] - sum[start] <= mid && end <= n) end++;//枚举当前分段的右端点 start = end - 1;//记录下一段的左端点 if (start == n) return 1; } } int main() { int ans = 0; scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) { int x; scanf("%d", &x); sum[i] = x + sum[i - 1];//前缀和 } int left = sum[1], right = sum[n]; while (left <= right) { int mid = (left + right) >> 1; if (check(mid)) ans = mid, right = mid - 1;//二分的答案其实就是题目的答案 else left = mid + 1; } printf("%d", ans); return 0; }
最新回复(0)