0w1

CFR 557 C. Arthur and Table ( DP )

Problem - 557C - Codeforces
題意:
一個桌子有若干個腳,每個腳用其高度和拔掉該腳所需花費描述。求最小總花費,使得最常的腳是絕對多數( 過所有腳數量一半 )。
解法:
利用各種預處理。枚舉最大長度後,透過各種前綴和快速得到更大長度的花費總和,接著枚舉花費,透過預處理快速得到拔除所需拔除的較小長度腳之最小總花費。

const int MAXL = ( int ) 1e5;
const int MAXD = 200;

int N;
vi L;
vi D;

void init(){
    cin >> N;
    L = D = vi( N );
    for( int i = 0; i < N; ++i )
        cin >> L[ i ];
    for( int i = 0; i < N; ++i )
        cin >> D[ i ];
}

vp ld; // pii( L, D )
vi lcnt; // count of L
vi plcnt; // prefix sum of count of L, [ 1, L )
vvi _d_l_cnt; // count of ( L, D )
vvi p_d_l_cnt; // under fixed D, prefix sum of count of L, [ D ][ 1, L )

void preprocess(){
    ld = vp( N );
    for( int i = 0; i < N; ++i )
        ld[ i ] = pii( L[ i ], D[ i ] );
    sort( ld.begin(), ld.end() );
    lcnt = vi( MAXL + 1 );
    for( int i = 0; i < N; ++i )
        ++lcnt[ L[ i ] ];
    plcnt = vi( MAXL + 1 );
    for( int i = 0; i < MAXL; ++i )
        plcnt[ i + 1 ] = plcnt[ i ] + lcnt[ i ];
    _d_l_cnt = vvi( MAXD + 1, vi( MAXL + 1 ) );
    for( int i = 0; i < N; ++i )
        ++_d_l_cnt[ D[ i ] ][ L[ i ] ];
    p_d_l_cnt = vvi( MAXD + 1, vi( MAXL + 1 ) );
    for( int i = 1; i <= MAXD; ++i )
        for( int j = 0; j < MAXL; ++j )
            p_d_l_cnt[ i ][ j + 1 ] = p_d_l_cnt[ i ][ j ] + _d_l_cnt[ i ][ j ];
}

void solve(){
    int ans = INF;
    for( int i = N - 1, ds = 0; 0 <= i; ds += ld[ i ].second, --i ){ // ds : sum of D for larger Ls
        if( i + 1 < N and ld[ i ].first == ld[ i + 1 ].second ) // if same L, then it had been considered, thus skip
            continue;
        int chcnt = 0, cost = 0, rmgol = max( 0, plcnt[ ld[ i ].first ] - ( lcnt[ ld[ i ].first ] - 1 ) ); // remove goal = count of smaller - ( count of cur - 1 )
        for( int j = 1; j <= MAXD; ++j ){
            chcnt += p_d_l_cnt[ j ][ ld[ i ].first ];
            cost += p_d_l_cnt[ j ][ ld[ i ].first ] * j;
            if( chcnt >= rmgol ){
                cost -= ( chcnt - rmgol ) * j;
                chcnt = rmgol;
                break;
            }
        }
        if( chcnt == rmgol )
            upmin( ans, cost + ds );
    }
    cout << ans << endl;
}