zoukankan      html  css  js  c++  java
  • Yet Another Minimization Problem

    Yet Another Minimization Problem

    一个很显然的决策单调性。

    方程是很显然的 $ f_i = min{f_{j-1} + w(j,i)} $ 。

    它具有决策单调性,可以参考钟神的 Blog

    我们考虑怎么实现这个东西,按照上次 DLS 讲的,考虑 solve(l,r,L,R) 表示 我们当前在处理 $ l,r $ 的 $ dp $ 值,我们知道当前决策点在 $ L,R $ 内。

    然后考虑怎么求,先对 $ mid $ 暴力跑出决策位置,然后分治 solve(l,mid-1,L,op),solve(mid+1,r,op,R)。复杂度是 $ nlogn $ 的,因为每一层分治的时间是 $ O(r - l + R - L) $

    但是还得求 $ w(l,r) $,这个东西我们可以直接类似莫队来算,因为总的移动的位置的和就是前面的 $ R - L $ 的和,这个是不影响复杂度的。

    代码很短,也很好写。。(没开llwa了两发

    #include "iostream"
    #include "algorithm"
    #include "cstring"
    #include "cstdio"
    using namespace std;
    #define MAXN 100006
    #define chkmn( a , b ) ( (a) > (b) ? ( (a) = (b) , 1 ) : 0 )
    #define chkmx( a , b ) ( (a) < (b) ? ( (a) = (b) , 1 ) : 0 )
    #define f( a ) ( (a) > 0 ? (a) : 0 )
    int n , k;
    int A[MAXN] , cn[MAXN];
    int L = 1 , R = 0;
    long long cw , dp[MAXN] , nw[MAXN];
    void upd(int c,int d){ cw += 1ll * d * cn[c] * (cn[c] - 1) / 2;}
    long long getw( int l , int r ) {
        while( L < l ) upd( A[L] , -1 ) , -- cn[A[L]] , upd( A[L] , 1 ) , ++ L;
        while( R > r ) upd( A[R] , -1 ) , -- cn[A[R]] , upd( A[R] , 1 ) , -- R;
        while( L > l ) -- L , upd( A[L] , -1 ) , ++ cn[A[L]] , upd( A[L] , 1 );
        while( R < r ) ++ R , upd( A[R] , -1 ) , ++ cn[A[R]] , upd( A[R] , 1 );
        return cw;
    }
    void solve( int l , int r , int L , int R ) {
        if( l > r ) return;
        int mid = l + r >> 1 , op; nw[mid] = 0x3f3f3f3f3f3f3f3f;
        for( int i = min( R , mid ) ; i >= L ; -- i ) {
            if( chkmn( nw[mid] , dp[i - 1] + getw( i , mid ) ) ) op = i;
        }
        if( l == r ) return;
        solve( l , mid - 1 , L , op ) , solve( mid + 1 , r , op , R );
    }
    int main() {
        cin >> n >> k;
        for( int i = 1 ; i <= n ; ++ i ) scanf("%d",&A[i]);
        memset( dp , 0x3f3f , sizeof dp ) , memset( nw , 0x3f3f , sizeof nw ) , dp[0] = 0;
        for( int i = 1 ; i <= k ; ++ i ) {
            solve( 1 , n , 1 , n );
            swap( nw , dp );
        }
        cout << dp[n] << endl;
    }
    
  • 相关阅读:
    linux(centos6.9) 安装mongoDB
    vue $refs
    vue $emit的使用方式
    docker上部署一个项目常用命令
    Nginx之Location匹配规则
    Github Packages和Github Actions实践之CI/CD
    消息中间件选型分析:从 Kafka 与 RabbitMQ 的对比看全局
    发布Jar包到maven中央仓库
    一些小Tip
    有风格的程序员,写有风格的代码
  • 原文地址:https://www.cnblogs.com/yijan/p/12323459.html
Copyright © 2011-2022 走看看