跳转至

NOIP 2016 普及组初赛试题 郊游活动 贪心+二分

  1. 贪心:先选带钱多的学生去租车,先选价格低的车去租。这样才能最大化利用 活动总经费
  2. 第4个空,if (____) 这个check( )函数对边界判断需要多思考一二,是小于,还是小于等于
// 利用单调性,左边都是满足条件的,求的是尽可能多的边界,所以left是答案
// check(mid)落到符合要求的区间,就更新左边界

// 一种二分模板
// l < r

#include <iostream>
using namespace std;

#define MAXN 1000000

int n, B, A, M[MAXN], C[MAXN], l, r, ans, mid;

bool check(int nn) {  //判断nn个人能不能骑上自行车,返回的是nn人能骑上
    int count = 0, i, j;

    i = n- nn + 1;
    j = 1;
    while (i <= n) {
        if(C[j] > M[i])
            count += C[j] - M[i];  //自行车的钱 - 小孩兜里的钱   需要多少资金的支持

        i++;
        j++;
    }

    return count <= A;    //资金够不够用
}

void sort(int a[], int l, int r) {
    int i = l, j = r, x = a[(l + r) / 2], y;
    while (i <= j) {
        while (a[i] < x) i++;
        while (a[j] > x) j--;
        if (i <= j) {
            y = a[i]; a[i] = a[j]; a[j] = y;
            i++; j--;
        }
    }
    if (i < r) sort(a, i, r);
    if (l < j) sort(a, l, j);
}

int main() {
    int i;
    cin >> n >> B >> A;
    for (i = 1; i <= n; i++) cin >> M[i];
    for (i = 1; i <= B; i++) cin >> C[i];

    sort(M, 1, n);
    sort(C, 1, B);

    l = 0; r = n;
    while (l < r) {
        mid = (l + r + 1) / 2;
        if(check(mid)){    //mid人能不能骑上骑自行车
            l = mid;
            ans = mid;
        }else
            r = mid - 1;
    }

    cout << ans << endl;

    return 0;
}
// 题目的二分模板
// l <= r

#include <iostream>
using namespace std;

#define MAXN 1000000

int n, B, A, M[MAXN], C[MAXN], l, r, ans, mid;

bool check(int nn) {  //判断nn个人能不能骑上自行车,返回的是nn人能骑上
    int count = 0, i, j;

    i = n- nn + 1;
    j = 1;
    while (i <= n) {
        if(C[j] > M[i])
            count += C[j] - M[i];  //自行车的钱 - 小孩兜里的钱   需要多少资金的支持

        i++;
        j++;
    }

    return count <= A;    //资金够不够用
}

void sort(int a[], int l, int r) {
    int i = l, j = r, x = a[(l + r) / 2], y;
    while (i <= j) {
        while (a[i] < x) i++;
        while (a[j] > x) j--;
        if (i <= j) {
            y = a[i]; a[i] = a[j]; a[j] = y;
            i++; j--;
        }
    }
    if (i < r) sort(a, i, r);
    if (l < j) sort(a, l, j);
}

int main() {
    int i;
    cin >> n >> B >> A;
    for (i = 1; i <= n; i++) cin >> M[i];
    for (i = 1; i <= B; i++) cin >> C[i];

    sort(M, 1, n);
    sort(C, 1, B);

    l = 0; r = n;
    while (l <= r) {
        mid = (l + r + 1) / 2;
        if(check(mid)){    //mid人能不能骑上骑自行车
            l = mid + 1;
            ans = mid;
        }else
            r = mid - 1;
    }

    cout << ans << endl;

    return 0;
}
// 自己重新写了一下

#include <bits/stdc++.h>

using namespace std;

const int N = 10010;

int n, B, A;
int M[N], C[N];

bool check(int nn)
{
    int cnt = 0;

    int i = n - nn + 1, j = 1;
    while (i <= n){
        if (C[j] > M[i]) cnt += C[j] - M[i];
        i++, j++;
    }

    return cnt <= A;
}

int main()
{
    cin >> n >> B >> A;
    for (int i = 1; i <= n; i++) cin >> M[i];
    for (int i = 1; i <= n; i++) cin >> C[i];

    sort(M + 1, M + 1 + n);
    sort(C + 1, C + 1 + n);

    int l = 0, r = n, best = 0;
    while (l < r){
        int mid = (l + r + 1) >> 1;
        if (check(mid)){
            l = mid;
            best = mid;
        }
        else{
            r = mid - 1;
        }
    }

    cout << best << '\n';

    return 0;
}