对于 Q2,固定一段连续行后,从左到右“当前列块一旦达到 x 就立即切开”能够得到最多的合法列块。外层同理:一旦当前若干行已经能够切出 B 个合法列块,就立即结束这一条水平带。由于权值非负,提前切割只会给后面的水平带留下更多行和权值,不会降低后续可行性。若存在某个可行划分,贪心得到的第一条水平带结束位置不会晚于该划分;删去第一条带后可以重复这一论证,所以最终切出的水平带数量是最大的。
▶
二分上下界
1 2 3 4 5 6 7 8 9 10 11 12
// Q1 寻找最小可行值 while( l <= r ) { ll mid = ( l + r ) >> 1; if( check( mid ) ) ans = mid, r = mid - 1; else l = mid + 1; } // Q2 寻找最大可行值 while( l <= r ) { int mid = ( l + r ) >> 1; if( check( mid ) ) ans = mid, l = mid + 1; else r = mid - 1; }
double l = lower, r = upper; for( int k = 0; k < 100; ++ k ) { double mid = (l + r) / 2.0; if( check( mid ) ) l = mid; else r = mid; } cout << l << '\n';
boolcheck( int x ){ ll cnt = 0; for( int i = 1; i <= n; ++ i ) { cnt += a[i] / x; } return cnt >= k; }
voidsolve( ){ cin >> n >> k; for( int i = 1; i <= n; ++ i ) cin >> a[i];
int l = 1, r = *max_element( a + 1, a + n + 1 ), ans = 0; while( l <= r ) { int mid = ( l + r ) >> 1; if( check( mid ) ) ans = mid, l = mid + 1; else r = mid - 1; } cout << ans << '\n'; }
boolcheck( ll x ){ ll sum = 0; int cnt = 1; // 默认至少有 1 组 for( int i = 1; i <= n; ++ i ) { if( sum + a[i] > x ) { sum = a[i]; cnt ++; } else { sum += a[i]; } } return cnt <= m; }
voidsolve( ){ cin >> n >> m; ll l = 0, r = 0, ans = 0; for( int i = 1; i <= n; ++ i ) { cin >> a[i]; l = max( l, a[i] ); r += a[i]; }
while( l <= r ) { ll mid = ( l + r ) >> 1; if( check( mid ) ) ans = mid, r = mid - 1; else l = mid + 1; } cout << ans << '\n'; }
boolcheck( int mid ){ int lst = 0, tot = 0; for( int i = 1; i <= r; ++ i ) { int s = 0, cnt = 0; for( int j = 1; j <= c; ++ j ) { s += sum[i][j] - sum[lst][j]; if( s >= mid ) cnt ++, s = 0; } if( cnt >= b ) { lst = i; tot ++; } } return tot >= a; }
voidsolve( ){ cin >> r >> c; cin >> a >> b; for( int i = 1; i <= r; ++ i ) { for( int j = 1; j <= c; ++ j ) { cin >> arr[i][j]; sum[i][j] = sum[i-1][j] + arr[i][j]; } }
int ans = 0; int l = 0, r = inf; while( l <= r ) { int mid = ( l + r ) >> 1; if( check( mid ) ) ans = mid, l = mid + 1; else r = mid - 1; } cout << ans << '\n'; }
boolcheck( int x ){ int cnt = 0; for( int i = 1; i < n; ++ i ) { if( a[i+1] - a[i] > x ) { cnt += ( a[i+1] - a[i] - 1 ) / x; } } return cnt <= k; }
voidsolve( ){ cin >> L >> n >> k; for( int i = 1; i <= n; ++ i ) cin >> a[i];
int l = 1, r = L, ans = 0; while( l <= r ) { int mid = ( l + r ) >> 1; if( check( mid ) ) ans = mid, r = mid - 1; else l = mid + 1; } cout << ans << '\n'; }
boolcheck( int x ){ int cnt = 0, last = 0; for( int i = 1; i <= n + 1; ++ i ) { if( a[i] - last < x ) cnt ++; else last = a[i]; } return cnt <= m; }
voidsolve( ){ cin >> L >> n >> m; for( int i = 1; i <= n; ++ i ) cin >> a[i]; a[n + 1] = L;
int l = 1, r = L, ans = 0; while( l <= r ) { int mid = ( l + r ) >> 1; if( check( mid ) ) ans = mid, l = mid + 1; else r = mid - 1; } cout << ans << '\n'; }
boolcheck( double mid ){ sum[0] = 0; for( int i = 1; i <= n; ++ i ) { sum[i] = sum[i - 1] + ( a[i] - mid ); } deque<int> q; for( int i = s; i <= n; ++ i ) { // 入队 while( !q.empty( ) && sum[ q.back( ) ] >= sum[i - s] ) q.pop_back( ); q.push_back( i - s ); // 出队 while( !q.empty( ) && q.front( ) < i - t ) q.pop_front( ); // 统计 if( !q.empty( ) && sum[i] - sum[ q.front( ) ] >= 0 ) return1; } return0; }
voidsolve( ){ cin >> n >> s >> t; double l = inf, r = -inf; for( int i = 1; i <= n; ++ i ) { cin >> a[i]; l = min( l, a[i] ); r = max( r, a[i] ); } // 实数二分 for( int k = 1; k <= 100; ++ k ) { double mid = ( r + l ) / 2.0; if( check( mid ) ) l = mid; else r = mid; } cout << fixed << setprecision(3) << l << '\n'; }
boolcheck( double mid ){ for( int i = 0; i <= n; ++ i ) { f[i] = sum[i] - mid * i; }
double mn = inf; int l = 0; for( int r = 1; r <= n; ++ r ) { while( l < r && k <= sum[r] - sum[l] ) { mn = min( mn, f[l] ); l ++; } if( f[r] >= mn ) returntrue; } returnfalse; }
voidsolve( ){ n = read( ), k = read( ); string s; cin >> s;
for( int i = 1; i <= n; ++ i ) { sum[i] = sum[i - 1] + ( s[i - 1] == 'o' ); }
double l = 0, r = 1; for( int t = 1; t <= 100; ++ t ) { double mid = ( l + r ) / 2.0; if( check( mid ) ) l = mid; else r = mid; } cout << fixed << setprecision( 6 ) << l << '\n'; }
boolcheck( double mid ){ for( int i = 1; i <= n; ++ i ) { dist[i] = 0; vis[i] = 0; } for( int i = 1; i <= n; ++ i ) { if( has_neg_cycle( i, mid ) ) return1; } return0; }
voidsolve( ){ cin >> n >> m; for( int i = 1; i <= m; ++ i ) { int u, v; double w; cin >> u >> v >> w; adj[u].push_back({ v, w }); } double l = -1e7, r = 1e7, ans = 0; for( int i = 1; i <= 100; ++ i ) { double mid = ( l + r ) / 2.0; if( check( mid ) ) ans = mid, r = mid; else l = mid; } cout << fixed << setprecision(8) << ans << '\n'; }
int l = 1, r = m, ans = 0; while ( l <= r ) { int mid = ( l + r ) >> 1; if ( check( mid ) ) l = mid + 1; // 这里我们的答案是 不满足条件 的情况! else ans = mid, r = mid - 1; }
ll check( ll W ){ memset( cnt, 0, sizeof( cnt ) ); memset( sumv, 0, sizeof( sumv ) ); for ( int i = 1; i <= n; ++ i ) { cnt[i] = cnt[i-1]; sumv[i] = sumv[i-1]; if ( w[i] >= W ) { cnt[i] += 1; sumv[i] += v[i]; } }
ll Y = 0; for ( int i = 1; i <= m; ++ i ) { Y += ( cnt[R[i]] - cnt[L[i] - 1] ) * ( sumv[R[i]] - sumv[L[i] - 1] ); } return Y; }
voidsolve( ){ cin >> n >> m >> s; ll max_w = 0; for( int i = 1; i <= n; ++ i ) { cin >> w[i] >> v[i]; max_w = max( max_w, w[i] ); }
for( int i = 1; i <= m; ++ i ) { cin >> L[i] >> R[i]; }
ll l = 0, r = max_w + 1; ll ans = inf;
while( l <= r ) { ll mid = l + ( ( r - l ) >> 1 ); ll res = check( mid ); ans = min( ans, abs( res - s ) ); if( res > s ) l = mid + 1; else r = mid - 1; }
int up[maxn][maxlg], dep[maxn]; int dist[maxn], edgew[maxn];
structPath { int u, v, lca, len; } p[maxn]; int diff[maxn], sum[maxn]; int max_len, max_edge, max_weight; int n, m;
voiddfs( int u, int p, int w ){ dep[u] = dep[p] + 1; up[u][0] = p; dist[u] = dist[p] + w; edgew[u] = w; for( int i = 1; i < maxlg; ++ i ) up[u][i] = up[up[u][i - 1]][i - 1]; for( auto &[v, w] : adj[u] ) if( v != p ) dfs( v, u, w ); }
intget_lca( int u, int v ){ if( dep[u] < dep[v] ) swap( u, v ); int diff = dep[u] - dep[v]; for( int i = 0; i < maxlg; ++ i ) if( ( diff >> i ) & 1 ) u = up[u][i]; if( u == v ) return u; for( int i = maxlg - 1; i >= 0; -- i ) if( up[u][i] != up[v][i] ) u = up[u][i], v = up[v][i]; return up[u][0]; }
voiddfs_sum( int u, int p, int cnt ){ sum[u] = diff[u]; for( auto &[v, w] : adj[u] ) if( v != p ) dfs_sum( v, u, cnt ), sum[u] += sum[v]; if( sum[u] == cnt ) max_edge = max( max_edge, edgew[u] ); }
boolcheck( int mid ){ int cnt = 0; for( int i = 1; i <= n; ++ i ) diff[i] = 0; for( int i = 1; i <= m; ++ i ) { if( p[i].len <= mid ) continue; cnt ++; diff[p[i].u] ++, diff[p[i].v] ++; diff[p[i].lca] -= 2; } if( cnt == 0 ) return1; max_edge = 0; dfs_sum( 1, 0, cnt ); return max_len - max_edge <= mid; }
voidsolve( ){ n = read( ), m = read( ); for( int i = 1; i <= n - 1; ++ i ) { int u = read( ), v = read( ), w = read( ); adj[u].push_back({ v, w }); adj[v].push_back({ u, w }); max_weight = max( max_weight, w ); }
dfs( 1, 0, 0 ); for( int i = 1; i <= m; ++ i ) { p[i].u = read( ), p[i].v = read( ); p[i].lca = get_lca( p[i].u, p[i].v ); p[i].len = dist[p[i].u] + dist[p[i].v] - 2 * dist[p[i].lca]; max_len = max( max_len, p[i].len ); }
int l = max( 0, max_len - max_weight ), r = max_len, ans = max_len; while( l <= r ) { int mid = ( l + r ) >> 1; if( check( mid ) ) ans = mid, r = mid - 1; else l = mid + 1; } cout << ans << '\n'; return0; }