ACM:二分专题


注意:
        1、专题系列难度随机。由于有些OJ网站不易被打开,无法查看原题目,所以所有的题目链接都指向VJ(Virtual Judge)中对应的题目。VJ中有题目的原出处,需要的自取!
        2、为了让大家更易于理解AC码,每一道题的代码风格都用AI进行了优化。


A、跳石头(洛谷 P2678)

题目链接:跳石头(洛谷 P2678)

标签:二分

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n" 

int L, N, M;
int rock[50050];

bool check(int distance) {
	int removed = 0;
	int prerock = 0;
	for (int i = 0; i < N; ++i) {
		if (rock[i] - prerock < distance) {
			removed++;
		} else {
			prerock = rock[i];
		}
	}
	if (L - prerock < distance) {
		removed++;
	}
	return removed <= M;
}

int bsearch() {
	int  l = -1, r = L;
	while (l + 1 != r) {
		int mid = (l + r) / 2;
		if (check(mid)) {
			l = mid;
		} else {
			r = mid;
		}
	}
	return l;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	cin >> L >> N >> M;
	for (int i = 0; i < N; ++i) {
		cin >> rock[i];
	}
	if (N == 0 && M == 0) {
		cout << L << endl;
	} else {
		cout << bsearch() << endl;
	}
	return 0;
}    

B、木材加工(洛谷 P2440)

题目链接:木材加工(洛谷 P2440)

标签:二分

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"

int n, k;
int logs[100050];
int maxx = 0;

bool check(int mid) {
    if (mid == 0) {
        return true;
    }
    int cnt = 0;
    for (int i = 0; i < n; ++i) {
        cnt += logs[i] / mid;
    }
    return cnt >= k;
}

int bsearch() {
    int l = -1, r = maxx;
    while (l + 1 != r) {
        int mid = (l + r) / 2;
        if (check(mid)) {
            l = mid;
        } else {
            r = mid;
        }
    }
    return l;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> k;
    for (int i = 0; i < n; ++i) {
        cin >> logs[i];
        maxx = max(maxx, logs[i]);
    }
    cout << bsearch() << endl;
    return 0;
}    

C、Set or Decrease(CodeForces 1622C)

题目链接:Set or Decrease(CodeForces 1622C)

标签:二分

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define int long long

int a[200050], presum[200050];
int n, k;

bool cmp(int x, int y) {
    return x > y;
}

bool check(int mid) {
    for (int i = 0; i <= min(mid, n - 1); i++) {
        int mi = a[n] - (mid - i);
        int sum_ = presum[n - 1] - presum[i] + (i + 1) * mi;
        if (sum_ <= k) {
            return true;
        }
    }
    return false;
}

int bsearch(int sum, int k) {
    int l = -1, r = sum - k;

    while (l + 1 != r) {
        int mid = (l + r) / 2;

        if (check(mid)) {
            r = mid;
        } else {
            l = mid;
        }
    }

    return r;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int t;
    cin >> t;

    while (t--) {
        cin >> n >> k;
        int sum = 0;

        for (int i = 1; i <= n; i++) {
            cin >> a[i];
            sum += a[i];
        }

        sort(a + 1, a + 1 + n, cmp);

        for (int i = 1; i <= n; i++) {
            presum[i] = presum[i - 1] + a[i];
        }

        if (sum <= k) {
            cout << 0 << endl;
        } else {
            int ans = bsearch(sum, k);
            cout << ans << endl;
        }
    }

    return 0;
}

D、Ice Cream Balls(CodeForces 1862D)

题目链接:Ice Cream Balls(CodeForces 1862D)

标签:二分

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"

long long n;

bool check(long long x) {
    long long temp = x * (x - 1) / 2;
    return temp <= n;
}

long long bsearch() {
    long long l = -1, r = 2e9;
    while (l + 1 != r) {
        long long mid = (l + r) / 2;
        if (check(mid)) {
            l = mid;
        } else {
            r = mid;
        }
    }
    return l;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int t;
    cin >> t;
    while (t--) {
        cin >> n;
        if (n == 1) {
            cout << 2 << endl;
            continue;
        }
        long long result = bsearch();
        cout << result + (n - (result * (result - 1) / 2)) << endl;
    }
    return 0;
}

E、Vika and the Bridge(CodeForces 1848B)

题目链接:Vika and the Bridge(CodeForces 1848B)

标签:二分

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"

bool check(int mid, const vector<int>& pos, int n) {
    int m = pos.size();
    int last = -1;
    int repaint = 0;

    for (int i = 0; i < m; ++i) {
        int gap = pos[i] - last - 1;
        if (gap > mid) {
            repaint++;
            if (repaint > 1) {
                return false;
            }
            if (gap / 2 > mid) {
                return false;
            }
        }
        last = pos[i];
    }

    int gap = n - pos.back() - 1;
    if (gap > mid) {
        repaint++;
        if (repaint > 1) {
            return false;
        }
        if (gap / 2 > mid) {
            return false;
        }
    }

    return true;
}

int bsearch(const vector<int>& pos, int n) {
    int l = -1, r = n;

    while (l + 1 != r) {
        int mid = (l + r) / 2;

        if (check(mid, pos, n)) {
            r = mid;
        } else {
            l = mid;
        }
    }

    return r;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int t;
    cin >> t;

    while (t--) {
        int n, k;
        cin >> n >> k;

        vector<int> c(n);
        for (int i = 0; i < n; ++i) {
            cin >> c[i];
        }

        vector<vector<int>> pos(k + 1);
        for (int i = 0; i < n; ++i) {
            pos[c[i]].push_back(i);
        }

        int ans = n;

        for (int color = 1; color <= k; ++color) {
            if (pos[color].empty()) {
                continue;
            }

            int min_max_step = bsearch(pos[color], n);
            ans = min(ans, min_max_step);
        }

        cout << ans << endl;
    }

    return 0;
}

F、Interview(CodeForces 1807E)

题目链接:Interview(CodeForces 1807E)

标签:二分

AC码:

#include <iostream>
using namespace std;
#define endl "\n"

const int MAXN = 100005;
int cows[MAXN];
int n, f;

bool check(double mid) {
    double presum[MAXN] = {};
    double min_sum = 0;

    for (int i = 1; i <= n; ++i) {
        presum[i] = presum[i - 1] + cows[i - 1] - mid;
    }

    for (int i = f; i <= n; ++i) {
        min_sum = min(min_sum, presum[i - f]);
        if (presum[i] - min_sum >= 0) {
            return true;
        }
    }

    return false;
}

double bsearch() {
    double l = 0, r = 2000;

    while (r - l > 1e-5) {
        double mid = (l + r) / 2.0;
        if (check(mid)) {
            l = mid;
        } else {
            r = mid;
        }
    }

    return r;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> f;
    for (int i = 0; i < n; ++i) {
        cin >> cows[i];
    }

    double result = bsearch();
    cout << int(result * 1000) << endl;

    return 0;
}

G、Chat Ban(CodeForces 1612C)

题目链接:CodeForces 1612C

标签:二分

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"

long long k, x;

bool check(long long mid) {
    if (mid <= k) {
        return (1 + mid) * mid / 2 >= x;
    }
    return (1 + k) * k / 2 + (k - 1 + 2 * k - mid) * (mid - k) / 2 >= x;
}

long long bsearch() {
    long long n = 2 * k - 1;
    long long l = -1, r = n;
    while (l + 1 != r) {
        long long mid = (l + r) / 2;
        if (check(mid)) {
            r = mid;
        } else {
            l = mid;
        }
    }
    return r;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t;
    cin >> t;
    while (t--) {
        cin >> k >> x;
        long long result = bsearch();
        cout << result << endl;
    }
    return 0;
}

H、Pursuit(CodeForces 1530C)

题目链接:Pursuit(CodeForces 1530C)

标签:二分

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"

int n;
vector<int> a, b;

bool cmp(int x, int y) {
    return x > y;
}

bool check(int mid) {
    int num = (n + mid) - (n + mid) / 4;
    int suma = 0, sumb = 0;
    vector<int> backupa = a;
    vector<int> backupb = b;

    for (int i = 0; i < mid; ++i) {
        backupa.push_back(100);
        backupb.push_back(0);
    }

    sort(backupa.begin(), backupa.end(), cmp);
    sort(backupb.begin(), backupb.end(), cmp);

    for (int i = 0; i < num; ++i) {
        suma += backupa[i];
        sumb += backupb[i];
    }

    return suma < sumb;
}

int bsearch() {
    int l = -1, r = 2 * n + 1;
    while (l + 1 != r) {
        int mid = (l + r) / 2;
        if (check(mid)) {
            l = mid;
        } else {
            r = mid;
        }
    }
    return r;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int t;
    cin >> t;
    while (t--) {
        a.clear();
        b.clear();
        cin >> n;

        int score;
        for (int i = 0; i < n; ++i) {
            cin >> score;
            a.push_back(score);
        }

        for (int i = 0; i < n; ++i) {
            cin >> score;
            b.push_back(score);
        }

        sort(a.begin(), a.end(), cmp);
        sort(b.begin(), b.end(), cmp);

        int sum1 = 0, sum2 = 0;
        for (int i = 0; i < n - n / 4; ++i) {
            sum1 += a[i];
            sum2 += b[i];
        }

        if (sum1 > sum2) {
            cout << 0 << endl;
        } else {
            cout << bsearch() << endl;
        }
    }
    return 0;
}

I、Best Cow Fences(POJ 2018)

题目链接:Best Cow Fences(POJ 2018)

标签:浮点二分

AC码:

#include <iostream>
using namespace std;
#define endl "\n"

const int MAXN = 100005;
int cows[MAXN];
int n, f;

bool check(double mid) {
    double presum[MAXN] = {};
    double min_sum = 0;

    for (int i = 1; i <= n; ++i) {
        presum[i] = presum[i - 1] + cows[i - 1] - mid;
    }

    for (int i = f; i <= n; ++i) {
        min_sum = min(min_sum, presum[i - f]);
        if (presum[i] - min_sum >= 0) {
            return true;
        }
    }

    return false;
}

double bsearch() {
    double l = 0, r = 2000;

    while (r - l > 1e-5) {
        double mid = (l + r) / 2.0;
        if (check(mid)) {
            l = mid;
        } else {
            r = mid;
        }
    }

    return r;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> f;
    for (int i = 0; i < n; ++i) {
        cin >> cows[i];
    }

    double ans = bsearch();
    cout << int(ans * 1000) << endl;

    return 0;
}

J、平均数(洛谷 P1404)

题目链接:平均数(洛谷 P1404)

标签:浮点二分

AC码:

#include <bits/stdc++.h>
using namespace std;
#define endl "\n"

double a[1000050], sum[1000050];
int n, m;

bool check(double mid) {
    for (int i = 1; i <= n; i++) {
        sum[i] = sum[i - 1] + (a[i] - mid);
    }

    double mi = 1e16;
    for (int i = m; i <= n; i++) {
        mi = min(mi, sum[i - m]);
        if (sum[i] - mi >= 0) {
            return true;
        }
    }
    return false;
}

int bsearch() {
    double l = 0, r = 1e9;
    while (r - l > 1e-7) {
        double mid = (l + r) / 2.0;
        if (check(mid)) {
            l = mid;
        } else {
            r = mid;
        }
    }
    return r * 1000;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }

    cout << bsearch() << endl;

    return 0;
}

K、

题目链接:

标签:二分+DFS/BFS,选最合适的一种

AC码:


L、Drying(POJ 3104)

题目链接:Drying(POJ 3104)

标签:二分

AC码:

#include <iostream>
#include <algorithm>
using namespace std;
#define endl "\n"

int n, k;
int a[100010];

bool check(int mid) {
    int sum = 0;
    for (int i = 0; i < n; ++i) {
        if (a[i] > mid) {
            sum += (a[i] - mid + k - 2) / (k - 1);
        }
        if (sum > mid) {
            return false;
        }
    }
    return true;
}

int bsearch() {
    int l = -1, r = a[n - 1];
    while (l + 1 != r) {
        int mid = (l + r) / 2;
        if (check(mid)) {
            r = mid;
        } else {
            l = mid;
        }
    }
    return r;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    while (cin >> n) {
        for (int i = 0; i < n; ++i) {
            cin >> a[i];
        }
        cin >> k;

        sort(a, a + n);

        if (k == 1) {
            cout << a[n - 1] << endl;
            continue;
        }

        int ans = bsearch();
        cout << ans << endl;
    }
    return 0;
}

结语

我只是一个A C M预习时长两年半的蒟蒻练习生,喜欢暴力,打表,面向样例编程,请各位键盘侠手下留情。
两年半

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-George-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值