# BZOJ 1044: [HAOI2008]木棍分割(二分答案 + dp)

-------------------------------------------------------------------------------------------------

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>

#define rep(i, n) for(int i = 0; i < n; ++i)
#define Rep(i, l, r) for(int i = l; i <= n; ++i)
#define clr(x, c) memset(x, c, sizeof(x))
#define mod(x) ((x + 10007) %= 10007)

using namespace std;

const int maxn = 50000 + 5;

int n, m, ans = 0;
int sumL[maxn];
int d[maxn][2];

scanf("%d%d", &n, &m);
int t;
sumL[0] = 0;
Rep(i, 1, n) {
scanf("%d", &t);
sumL[i] = sumL[i - 1] + t;
}
}

bool jud(int ans) {
int cnt = m, front = 0, rear = 0;
while(rear < n) {
while(rear < n && sumL[rear + 1] - sumL[front] <= ans) rear++;
if(rear < n) {
front = rear;
if(--cnt < 0) return false;
}
}
return true;
}

void BS() {
int l = 0, r = sumL[n];
while(l <= r) {
int mid = (l + r) >> 1;
if(jud(mid)) { ans = mid; r = mid - 1; }
else l = mid + 1;
}
printf("%d ", ans);
}

void DP() {
int cur = 0, Ans = 0;
Rep(i, 1, n) d[i][cur] = sumL[i] <= ans ? 1 : 0;
d[0][0] = d[0][1] = 0;
while(m--) {
cur ^= 1;
int p = 0, sum = 0;
Rep(i, 1, n) {
while(sumL[i] - sumL[p] > ans) mod(sum -= d[p++][cur ^ 1]);
mod(d[i][cur] = sum);
mod(sum += d[i][cur ^ 1]);
}
mod(Ans += d[n][cur]);
}
printf("%d\n", Ans);
}

int main() {
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
BS();
DP();
return 0;
}

-------------------------------------------------------------------------------------------------

## 1044: [HAOI2008]木棍分割

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2095  Solved: 761
[Submit][Status][Discuss]

3 2
1
1
10

10 2

## HINT

n<=50000, 0<=m<=min(n-1,1000).

1<=Li<=1000.

## Source

posted @ 2015-05-01 20:29  JSZX11556  阅读(200)  评论(0编辑  收藏