思路
一道dp题,就是转移方程需要思考,第一种情况肯定是直接连wife,第二种情况就是放置一个wife,第二种情况的转移方程为:dp[i]=min(dp[i],dp[j]+i-k),其中如果i这个位置被覆盖了,那么是在i-k的位置放置路由器,所以花费i-k,dp[j]是i-2*k到i位置的最小的dp值。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MXN = 2e5 + 5 ;
const int MXLOG = 18 ;
int lz[ MXN<< 2 ] , T[ MXN<< 2 ] ;
inline void pushUp ( int rt) {
T[ rt] = min ( T[ rt<< 1 ] , T[ rt<< 1 | 1 ] ) ;
}
void pushDown ( int rt) {
if ( lz[ rt] != LLONG_MAX/ 10 ) {
lz[ rt<< 1 ] = min ( lz[ rt] , lz[ rt<< 1 ] ) ;
lz[ rt<< 1 | 1 ] = min ( lz[ rt] , lz[ rt<< 1 | 1 ] ) ;
T[ rt<< 1 ] = min ( lz[ rt] , T[ rt<< 1 ] ) ;
T[ rt<< 1 | 1 ] = min ( lz[ rt] , T[ rt<< 1 | 1 ] ) ;
lz[ rt] = LLONG_MAX/ 10 ;
}
}
void build ( int l, int r, int rt) {
lz[ rt] = LLONG_MAX/ 10 ;
if ( l== r) {
T[ rt] = LLONG_MAX/ 10 ;
return ;
}
int m= ( l+ r) >> 1 ;
build ( l, m, rt<< 1 ) ;
build ( m+ 1 , r, rt<< 1 | 1 ) ;
pushUp ( rt) ;
}
void update ( int L, int R, int c, int l, int r, int rt) {
if ( l>= L&& r<= R) {
lz[ rt] = min ( lz[ rt] , c) ;
T[ rt] = min ( T[ rt] , c) ;
return ;
}
pushDown ( rt) ;
int m= ( l+ r) >> 1 ;
if ( m>= L) update ( L, R, c, l, m, rt<< 1 ) ;
if ( m< R) update ( L, R, c, m+ 1 , r, rt<< 1 | 1 ) ;
pushUp ( rt) ;
}
int query ( int L, int R, int l, int r, int rt) {
if ( l>= L&& r<= R)
return T[ rt] ;
pushDown ( rt) ;
int m= ( l+ r) >> 1 ;
int re= LLONG_MAX/ 10 ;
if ( m>= L) re= min ( re, query ( L, R, l, m, rt<< 1 ) ) ;
if ( m< R) re= min ( re, query ( L, R, m+ 1 , r, rt<< 1 | 1 ) ) ;
return re;
}
int to[ MXN] ;
int midPos[ MXN] ;
signed main ( ) {
int n, k; cin>> n>> k;
string s; cin>> s;
build ( 1 , n+ 1 , 1 ) ;
for ( int i= 1 ; i<= n; i++ ) to[ i] = n+ 1 ;
for ( int i= n- 1 ; i>= 0 ; i-- ) {
if ( s[ i] == '1' ) {
int ll= max ( 1LL , i+ 1 - k) , rr= min ( n, i+ 1 + k) ;
if ( ll<= to[ rr] ) to[ rr] = ll, midPos[ rr] = i+ 1 ;
}
}
update ( n+ 1 , n+ 1 , 0 , 1 , n+ 1 , 1 ) ;
for ( int i= n; i>= 1 ; i-- ) {
int t1= query ( i, i, 1 , n+ 1 , 1 ) , t2= query ( i+ 1 , i+ 1 , 1 , n+ 1 , 1 ) + i;
update ( i, i, min ( t1, t2) , 1 , n+ 1 , 1 ) ;
if ( to[ i] < i) update ( to[ i] , i, midPos[ i] + t2- i, 1 , n+ 1 , 1 ) ;
}
cout<< query ( 1 , 1 , 1 , n+ 1 , 1 ) ;
return 0 ;
}