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;
}
相关推荐
有点。1 小时前
C++二叉树(一)
开发语言·数据结构·c++
Lazionr1 小时前
stack与queue:底层实现与容器适配器
开发语言·数据结构·c++
豆沙沙包?2 小时前
C++~~~vector容器(p31-P40)
开发语言·c++
小小de风呀2 小时前
de风——【从零开始学习C++】(十八):AVL树——让二叉搜索树自己“站起来“的自平衡黑科技
c++·科技·学习
牛油果子哥q2 小时前
C++STL容器详解:vector/list/string底层扩容、迭代器失效终极解决、容器选型避坑
开发语言·c++·list
忍冬k3 小时前
DeepSeek harness安装指南
java·开发语言·数据结构·c++·算法
welfare9623 小时前
新号别搞:c++类与对象
开发语言·c++
举手3 小时前
Epoll模型
linux·c++·学习
Shadow(⊙o⊙)3 小时前
Linux网络部分——TCP服务端、客户端架构分析多进程、多线程、线程池
c++·tcp/ip·架构