其他分享
首页 > 其他分享> > CF161A - Dress'em in Vests!(暴力+贪心/二分/普及级)

CF161A - Dress'em in Vests!(暴力+贪心/二分/普及级)

作者:互联网

161A - Dress'em in Vests!(源地址自⇔CF161A

Problem

d9bb5fa25439d60d49b172dddd142dc8.png

d503bd1e1b9ddaf7becdac5f9be108e2.png

tag:

⇔暴力、⇔贪心、⇔二分、⇔普及级(*1300)

题意:

有 \(n\) 个士兵和 \(m\) 件背心,给出每个人的体型 \(a_i\) 和每件背心的大小 \(b_i\) ,当满足 \(a_i-x\leq b_j\leq a_i+y\) 时,说明第 \(j\) 件背心可以被第 \(i\) 个人穿上。使得尽可能多的士兵穿上背心,并输出这些匹配对。

思路1【二分】:

对于第 \(i\) 个士兵,二分查找可供挑选的背心,找到刚好穿上的那一件 \(b_j\) 。由于数据有序,对于下一个士兵 \(i+1\) ,他刚好能穿上的那一件大小必定大于 \(b_{j+1}\) ,故二分查找可供挑选的背心,范围是 \(j+1\) 到 \(m\) 。时间复杂度 \(O(n*log_2m)\) 。

思路2【暴力】:

上方的思路已经提到了查找范围的变化,而由于数据是有序的,只要遍历就可以。

对于第 \(i\) 个士兵,顺序查找可供挑选的背心,找到刚好穿上的那一件 \(b_j\) 。由于数据有序,对于下一个士兵 \(i+1\) ,他刚好能穿上的那一件大小必定大于 \(b_{j+1}\) ,故继续顺序查找可供挑选的背心,范围是 \(j+1\) 到 \(m\) 。时间复杂度 \(O(n+m)\) 。

AC代码1【二分】:

//A WIDA Project
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int MAX=1e6+5;
LL n, num, m, x, y, w, ans[MAX], Ans[MAX], start = 1, M[MAX], N[MAX], t;
int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin >> n >> m >> x >> y;
    for(int i = 1; i <= n; i ++) cin >> N[i];
    for(int i = 1; i <= m; i ++) cin >> M[i];
    for(int i = 1; i <= n; i ++) {
        t = lower_bound(M + start, M + 1 + m, N[i] - x) - M;
        if(M[t] <= N[i] + y && M[t] != 0) {
            num ++;
            ans[num] = i;
            Ans[num] = t;
            start = t + 1;
        }
    }
    cout << num << endl;
    for(int i = 1; i <= num; i ++) cout << ans[i] << " " << Ans[i] << endl;
    return 0;
}

AC代码2【暴力】:

//A WIDA Project
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int MAX=1e6+5;
LL n, num, m, x, y, w, ans[MAX], Ans[MAX], start = 1, M[MAX], N[MAX], t;
int main() {
    cin >> n >> m >> x >> y;
    for(int i = 1; i <= n; i ++) cin >> N[i];
    for(int i = 1; i <= m; i ++) cin >> M[i];
    for(int i = 1; i <= n; i ++) {
        while(start <= m && M[start] < N[i] - x) start ++;
        if(start <= m && M[start] <= N[i] + y) {
            num ++;
            ans[num] = i;
            Ans[num] = start;
            start ++;
        }
    }
    cout << num << endl;
    for(int i = 1; i <= num; i ++) cout << ans[i] << " " << Ans[i] << endl;
    return 0;
}

错误次数:7次【补题:3次】

原因:背心使用后没有更新新的查找范围,重复计算了 \(b_j\) ,而不是从 \(b_{j+1}\) 开始计算,WA。

原因:背心未被使用时(即某一士兵穿不上所有的背心)没有更新新的查找范围,TLE。

原因:背心使用后,更新新的查找范围多计算了一件,导致从 \(b_j+2\) 开始查找,而不是从 \(b_{j+1}\) 开始计算,WA。

原因:(同第一次)

原因:(同第二次)

原因:(本质上和第二次一样,略加了优化,但没有修改到本质,依旧TLE)

原因:二分范围取错,取了士兵的范围进行二分,而不是背心的范围,WA。


文 / WIDA
2021.11.6成文
首发于WIDA个人博客,仅供学习讨论


更新日记:
2021.11.6 成文

标签:em,二分,CF161A,Vests,背心,int,MAX,查找,士兵
来源: https://www.cnblogs.com/WIDA/p/15517646.html