2021年CSP-J初赛真题及答案解析(完善程序2)

2021年CSP-J初赛真题及答案解析(完善程序2)

第 2 题

矩形计数:平面上有 (n) 个关键点,求有多少个四条边都和 (x) 轴或者 (y) 轴平行的矩形,满足四个顶点都是关键点。给出的关键点可能有重复,但完全重合的矩形只计一次。

试补全枚举算法。

cpp 复制代码
#include <iostream>
using namespace std;

struct point {
    int x, y, id;
};

bool equals(point a, point b) {
    return a.x == b.x && a.y == b.y;
}

bool cmp(point a, point b) {
    return ①;
}

void sort(point A[], int n) {
    for (int i = 0; i < n; i++) {
        for (int j = 1; j < n; j++) {
            if (cmp(A[j], A[j - 1])) {
                point t = A[j];
                A[j] = A[j - 1];
                A[j - 1] = t;
            }
        }
    }
}

int unique(point A[], int n) {
    int t = 0;
    for (int i = 0; i < n; i++) {
        if (②)
            A[t++] = A[i];
    }
    return t;
}

bool binary_search(point A[], int n, int x, int y) {
    point p;
    p.x = x;
    p.y = y;
    p.id = n;
    int a = 0, b = n - 1;
    while (a < b) {
        int mid = ③;
        if (④)
            a = mid + 1;
        else
            b = mid;
    }
    return equals(A[a], p);
}

const int MAXN = 1000;
point A[MAXN];

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> A[i].x >> A[i].y;
        A[i].id = i;
    }
    sort(A, n);
    n = unique(A, n);
    int ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (⑤ && binary_search(A, n, A[i].x, A[j].y) && binary_search(A, n, A[j].x, A[i].y)) {
                ans++;
            }
        }
    }
    cout << ans << endl;
    return 0;
}

① 处应填( )

A. a.x != b.x ? a.x < b.x : a.id < b.id

B. a.x != b.x ? a.x < b.x : a.y < b.y

C. equals(a, b) ? a.id < b.id : a.x < b.x

D. equals(a, b) ? a.id < b.id : (a.x != b.x ? a.x < b.x : a.y < b.y)

② 处应填( )

A. i == 0 || cmp(A[i], A[i - 1])

B. t == 0 || equals(A[i], A[t - 1])

C. i == 0 || !cmp(A[i], A[i - 1])

D. t == 0 || !equals(A[i], A[t - 1])

③ 处应填( )

A. b - (b - a) / 2 + 1

B. (a + b + 1) >> 1

C. (a + b) >> 1

D. a + (b - a + 1) / 2

④ 处应填( )

A. !cmp(A[mid], p)

B. cmp(A[mid], p)

C. cmp(p, A[mid])

D. !cmp(p, A[mid])

⑤ 处应填( )

A. A[i].x == A[j].x

B. A[i].id < A[j].id

C. A[i].x == A[j].x && A[i].id < A[j].id

D. A[i].x < A[j].x && A[i].y < A[j].y


答案

  • B
  • D
  • C
  • B
  • D

解析

变量与函数作用
  • cmp(a, b):定义点的严格弱序,用于排序和二分查找。
  • sort(A, n):冒泡排序,按 cmp 确定的顺序将点排好。
  • unique(A, n):对已排序的数组去重,返回去重后元素个数。
  • binary_search(A, n, x, y):在有序数组 A 中二分查找坐标为 (x, y) 的点,存在返回 true
  • 主函数:排序、去重,然后枚举所有可能构成矩形左下角与右上角的点对,检查另外两个顶点是否存在,计数。

① 排序比较规则

排序时必须按点坐标大小排序,通常按 x 升序,x 相同则按 y 升序

  • a.x != b.x,按 a.x < b.x 决定。
  • a.x == b.x,按 a.y < b.y 决定。
    选项 B 完全符合,且当两点完全相同时,a.y < b.yfalse,满足严格弱序要求。
    其他选项引入了 idequals,会打乱坐标顺序,导致二分查找错误。
    答案:B

② 去重条件

去重时,当前元素 A[i] 应该被保留,当且仅当它是第一个元素(t == 0)或者它不等于 已保留的最后一个元素 A[t - 1]

因此条件应为:t == 0 || !equals(A[i], A[t - 1])

选项 D 正确。选项 B 是相等时保留,错误;A、C 使用 cmp 无法正确判断相等。

答案:D


③ 二分查找中间位置

标准二分查找中,mid = (a + b) / 2,在 C++ 中可写作 (a + b) >> 1

选项 C 正确。选项 B 是上取整,会破坏二分查找的稳定性;选项 A、D 写法错误。

答案:C


④ 二分查找移动方向

标准二分查找中,若 A[mid] < p,说明目标在右半部分,令 a = mid + 1;否则令 b = mid

这里的"小于"关系由 cmp(A[mid], p) 表示(若返回 true,则 A[mid] 排在 p 前面,即小于)。

因此 if (cmp(A[mid], p)) a = mid + 1;

选项 B 正确。选项 A 是 !cmp(A[mid], p),表示不小于,会令方向相反;C、D 比较方向颠倒。

答案:B


⑤ 避免矩形重复计数

一个矩形的四个顶点中,有且仅有一对点可作为左下角右上角 (x 和 y 都较小/较大)。

枚举时只统计 A[i].x < A[j].xA[i].y < A[j].y 的情况,这样每个矩形只会被计数一次。

同时,检查另外两个点 (A[i].x, A[j].y)(A[j].x, A[i].y) 是否存在。

选项 D 正确。其他选项如 A、B、C 无法保证唯一且正确的配对。

答案:D


更多内容请关注专栏:信奥赛C++普及组csp-j初赛&复赛真题题解(持续更新): https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转


【秘籍汇总】(完整csp信奥赛C++学习资料):

1、csp/信奥赛C++,完整信奥赛系列课程(永久学习):

https://edu.csdn.net/lecturer/7901 点击跳转

2、CSP信奥赛C++竞赛拿奖视频课:

https://edu.csdn.net/course/detail/40437 点击跳转

https://edu.csdn.net/course/detail/41081 点击跳转

3、csp信奥赛高频考点知识详解及案例实践:

CSP信奥赛C++动态规划:

https://blog.csdn.net/weixin_66461496/category_13096895.html点击跳转

CSP信奥赛C++标准模板库STL:

https://blog.csdn.net/weixin_66461496/category_13108077.html 点击跳转

信奥赛C++提高组csp-s知识详解及案例实践:

https://blog.csdn.net/weixin_66461496/category_13113932.html 点击跳转

4、csp信奥赛冲刺一等奖有效刷题题解:

信奥赛C++普及组CSP-J一等奖通关刷题题单及题解:

https://blog.csdn.net/weixin_66461496/category_12673810.html 点击跳转

信奥赛C++普及组csp-j初赛&复赛真题题解(持续更新): https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转

信奥赛C++提高组csp-s初赛&复赛真题题解(持续更新):

https://blog.csdn.net/weixin_66461496/category_13125089.html 点击跳转

5、GESP C++考级真题题解:

GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转

GESP(C++ 七级+八级)真题题解(持续更新):

https://blog.csdn.net/weixin_66461496/category_13117178.html 点击跳转

· 文末祝福 ·

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	cout<<"跟着王老师一起学习信奥赛C++";
	cout<<"    成就更好的自己!       ";
	cout<<"  csp信奥赛一等奖属于你!   ";
	return 0;
}
相关推荐
HugoStudio_SWAN2 小时前
洛谷 P1420 / P1179 / B4262 最长连号、数字统计与词频统计——统计的三种面孔
c++·学习·程序人生·算法
raindayinrain3 小时前
c++并发
c++
j7~3 小时前
【C++】智能指针的使用及其原理--详解
c++·c++11·内存泄漏·智能指针·raii·boost智能指针
Persistent的粽子!4 小时前
C++:类与对象(一)
开发语言·c++·经验分享·笔记
库玛西4 小时前
深入浅出Linux select网络模型:从底层位图原理到C++面向对象高级封装
linux·服务器·网络·c++·ubuntu
2402_882893865 小时前
深入浅出 unordered_map 与 unordered_set——从使用到底层差异
c++·哈希·unordered_map·unordered_set
今天要早睡_5 小时前
C++ 核心语法速过:命名空间、引用、函数重载与 nullptr 深度解析
android·java·c++
汉克老师6 小时前
CSP-J 初赛(以满分为目标):第二十七课 《图的遍历——BFS广度优先搜索——像“水波纹”一样,一层一层地搜索》
c++·csp-j·小学生·学c++编程
闻缺陷则喜何志丹6 小时前
【动态规划】P3609 [USACO17JAN] Hoof, Paper, Scissor G
c++·算法·动态规划·洛谷
汉克老师6 小时前
CSP-J 初赛(以满分为目标):第二十六课 《图的遍历——DFS深度优先搜索——从“树的先序遍历”走进真正的图世界》
c++·csp-j·小学生·学c++编程