BZOJ-1044: [HAOI2008]木棍分割(二分+贪心+

作者: acccccc | 来源:发表于2019-02-16 20:10 被阅读0次

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1044

第一问用二分+贪心很好解决就不说了,设第一问答案为ANS0

第二问DP,令f[ i ][ j ]表示砍了i次,最后一次砍在j这个地方的方案数,那么f[ i ][ j ] = sigma( f[ i - 1 ][ k ] ) ( dist( k , j ) <= ANS0 , k < j ) , 然后我们发现k范围的左区间是递增的,那么用一个变量O( 1 )维护sigma( f[ i - 1 ][ k ] ),接下来滚动数组节省一下空间就可以O(NM)啦。

代码:

#include <cstdio>
#include <algorithm>
#include <cstring>
 
using namespace std ;
 
const int maxn = 50010 , maxm = 1010 , mod = 10007 ;
 
int a[ maxn ] , ans0 , n , m , sum = 0 , pre[ maxn ] ;
 
bool check( int x ) {
    int cnt = 1 , rec = 0 ; 
    for ( int i = 0 ; i ++ < n ; ) if ( rec + a[ i ] <= x ) {
        rec += a[ i ] ;
    } else {
        if ( a[ i ] > x ) return false ;
        rec = a[ i ] , cnt ++ ; 
    }
    return cnt <= m + 1 ;
}
 
int solve0(  ) {
    int l = 0 , r = sum , mid ; 
    while ( r - l > 1 ) {
        mid = ( l + r ) >> 1 ; 
        if ( check( mid ) ) r = mid ; else l = mid ;
    }
    return r ; 
}
 
int f[ 2 ][ maxn ] , k = 0 ; 
 
void update( int &val , int delta ) {
    val = ( val + delta + mod ) % mod ;
}
 
int dp(  ) {
    memset( f[ 0 ] , 0 , sizeof( f[ 0 ] ) ) ;
    f[ 0 ][ 0 ] = 1 ; 
    int ans1 = 0 ; 
    for ( int i = 0 ; i ++ < m ; ) {
        int temp = f[ k ][ 0 ] , pos = 0 ; 
        memset( f[ k ^ 1 ] , 0 , sizeof( f[ k ^ 1 ] ) ) ;
        for ( int j = 1 ; j < n ; ++ j ) {
            for ( ; pre[ j ] - pre[ pos ] > ans0 ; update( temp , - f[ k ][ pos ++ ] ) ) ;
            if ( j - 1 ) update( temp , f[ k ][ j - 1 ] ) ;
            f[ k ^ 1 ][ j ] = temp ;
            if ( pre[ n ] - pre[ j ] <= ans0 ) update( ans1 , temp ) ;
        }
        k ^= 1 ;
    }
    return ans1 + ( pre[ n ] <= ans0 ) ;
}
 
int main(  ) {
    scanf( "%d%d" , &n , &m ) ;
    pre[ 0 ] = 0 ;
    for ( int i = 0 ; i ++ < n ; ) {
        scanf( "%d" , a + i ) ;
        sum += a[ i ] , pre[ i ] = pre[ i - 1 ] + a[ i ] ;
    }
    printf( "%d " , ans0 = solve0(  ) ) ;
    printf( "%d\n" , dp(  ) ) ;
    return 0 ; 
}

相关文章

  • BZOJ-1044: [HAOI2008]木棍分割(二分+贪心+

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1044 第...

  • 程序员进阶之算法练习(二十八)

    前言 四道题,分别锻炼哈希、贪心、贪心+排序、二分四个能力。第一题较为简单,后续的题目都需要一定的基础。贪心是最基...

  • [贪心]木棍加工—洛谷P1233

    传送门 木棍加工P1233 思路   根据题目,很自然的能想到,先加工 和的值最大的。蛋似,并没有那么好的事情,可...

  • Educational Codeforces Round 64

    比赛链接:https://codeforces.com/contest/1156 C 二分、贪心 题目链接:htt...

  • 300. 最长递增子序列

    解法 动态规划,时间复杂度为O(N * N) 贪心算法+二分查找,O(NlogN)

  • dp(0)背包

    假定物品为i,背包容量为v:之前靠贪心解,优先放性价比最高的。但是贪心只适用于可以连续分割 完全背包(参见hiho...

  • 算法入门(4)奶牛二分

    疯牛问题的二分贪心算法:加入二分查找速度快了不少。这里把r的最大值设置为: int((N[-1] - N[0])/...

  • 入门算法:归并排序

    上手难度:★★☆ 算法复杂度:O(nlogn) 排序思想: 将数组采用二分法,不断的递归分割,直至分割到单个元素,...

  • 木棍

    印象中,那张略显严肃的脸似乎并不会笑。如果说他的脸是一张洁白地一尘不染的素描纸的话,那么将他那“万年不改”...

  • 621. 任务调度器/875. 爱吃香蕉的珂珂

    621. 任务调度器 相关标签: 贪心 数组 队列 875. 爱吃香蕉的珂珂 相关标签: 二分查找

网友评论

    本文标题:BZOJ-1044: [HAOI2008]木棍分割(二分+贪心+

    本文链接:https://www.haomeiwen.com/subject/gsvieqtx.html