本部分总题单如下
【腾讯文档】副本-CSP-JS+NOI 题单 (未完待续)
https://docs.qq.com/sheet/DSmJuVXR4RUNVWWhW?tab=BB08J2
https://www.luogu.com.cn/problem/P1678
计算机竞赛小组的神牛 V 神终于结束了高考,然而作为班长的他还不能闲下来,班主任老 t 给了他一个艰巨的任务:帮同学找出最合理的大学填报方案。可是 v 神太忙了,身后还有一群朋友等着和聚餐
,于是他想到了同为计算机竞赛小组的你,请你帮他完成这个艰巨的任务。
现有 m 所学校,每所学校预计分数线是 a_i 。有 n 位学生,估分分别为 b_i 。
根据 n 位学生的估分情况,分别给每位学生推荐一所学校,要求学校的预计分数线和学生的估分相差最小(可高可低,毕竟是估分嘛),这个最小值为不满意度。求所有学生不满意度和的最小值。
第一行读入两个整数 m,n 。
第二行共有 m 个数,表示 m 个学校的预计录取分数。
第三行有 n 个数,表示 n 个学生的估分成绩。
输出一行,为最小的不满度之和。
4 3
513 598 567 689
500 600 550
32
数据范围:
对于 30\% 的数据,1\leq n,m\leq10^3 ,估分和录取线 \leq10^4 ;
对于 100\% 的数据,1\leq n,m\leq10^5 ,估分和录取线 \leq 10^6 且均为非负整数。
#include<bits/stdc++.h>
using namespace std;
int m,n;//m个学校 n个学生
int school[100100],students[100100];
int main(){
// freopen("C:\\Users\\zhangjun\\Downloads\\P1678_1.in","r",stdin);
// freopen("C:\\Users\\zhangjun\\Downloads\\P1678_1.inOUT","w",stdout);
cin>>m>>n;
for(int i=1;i<=m;i++){
scanf("%d",&school[i]);
}
for(int i=1;i<=n;i++){
scanf("%d",&students[i]);
}
// for(int i=1;i<=m;i++){
// printf("%d ",school[i]);
// }
// cout<<endl;
// for(int i=1;i<=n;i++){
// printf("%d ",students[i]);
// }
// 累加器
int sum=0;
// 遍历每个学生
for(int i=1;i<=n;i++){
// 完成学生与每个学校分数的比较,
// 并找出最小值
int minDifference=9999999;
// 遍历每个学校
for(int j=1;j<=m;j++){
if(minDifference>abs(students[i]-school[j])) {
minDifference=abs(students[i]-school[j]);
}
}
sum+=minDifference;
}
cout<<sum;
return 0;
}
#include <iostream>
#include <cmath>
#include <algorithm> // 提供 sort 函数
using namespace std;
// 数组 a 存储学校分数线(最多 100100 个)
// 数组 b 存储学生估分成绩(最多 100100 个)
int a[100100], b[100100];
int main() {
int n, m; // n: 学校数量, m: 学生数量
cin >> n >> m;
// 输入每个学校的分数线
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
// 输入每个学生的估分
for (int i = 1; i <= m; ++i) {
cin >> b[i];
}
// 将学校分数线从小到大排序
sort(a + 1, a + n + 1);
int ans = 0; // 不满意度总和
// 遍历每位学生
for (int i = 1; i <= m; ++i) {
int target = b[i]; // 当前学生的估分
// 设置初始搜索范围 [l, r)
int l = 1, r = n + 1;
// 找第一个 > target 的位置
while (l < r) {
int mid = (l + r) / 2;
if (a[mid] <= target) {
l = mid + 1; // 如果当前值小于等于目标,说明要往右找更大的
} else {
r = mid; // 否则往左缩
}
}
// 此时 l 是第一个 > target 的位置
// 最接近的两个是:a[l-1] 和 a[l]
// 特判:如果所有学校分数都比 target 大
if (target <= a[1]) {
ans += a[1] - target;
} else {
// 比较 a[l-1] 和 a[l] 哪个更近
ans += min(abs(a[l - 1] - target), abs(a[l] - target));
}
}
// 输出最终结果
cout << ans << endl;
return 0;
}
#include <iostream> // 输入输出流
#include <cmath> // 提供 abs() 等数学函数
#include <algorithm> // 提供 sort(), lower_bound() 等算法函数
using namespace std;
// 定义最大数据范围:1e5 + 10,避免数组越界
const int MAXN = 1e5 + 10;
// a 数组存储学校分数线
// b 数组存储学生估分成绩
int a[MAXN], b[MAXN];
int main() {
// n: 学校数量, m: 学生数量
int n, m;
cin >> n >> m;
// 读取每个学校的分数线到数组 a 中
for (int i = 0; i < n; ++i)
cin >> a[i];
// 对 a 数组进行排序,方便后面使用二分查找
sort(a, a + n);
// ans 记录所有学生的不满意度总和
long long ans = 0;
// 遍历每个学生
for (int i = 0; i < m; ++i) {
// 读取当前学生的估分成绩
cin >> b[i];
// 使用 lower_bound 查找第一个 **大于等于** 当前学生成绩 b[i] 的位置
// 返回的是一个指针,指向找到的位置
int* it = lower_bound(a, a + n, b[i]);
// 初始化差值为一个非常大的数
int diff = 2e9;
// 如果 it 没有越界(即不是 a + n),说明找到了 >= b[i] 的元素
if (it != a + n)
diff = abs(*it - b[i]); // 计算与这个学校的差值
// 如果 it 不是数组开头(即不是 a),说明存在前面那个更小的元素
if (it != a)
diff = min(diff, abs(*(it - 1) - b[i])); // 和前一个比较,取最小值
// 将当前学生的不满意度加入总和
ans += diff;
}
// 输出最终结果
cout << ans << endl;
return 0;
}
lower_bound
的详细介绍template<class ForwardIt, class T>
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value);
[first, last)
中查找第一个 不小于(>=)value 的元素。last
。以数组为例:
int arr[] = {1, 3, 5, 7, 9};
int* it = lower_bound(arr, arr + 5, 6);
{1, 3, 5, 7, 9}
中查找第一个 >= 6
的元素;7
,它在索引 3;it == &arr[3]
。lower_bound
是基于二分查找实现的,只适用于有序数组;a
,那么 it
是一个 int*
类型;*it
获取值,也可以通过 it - a
得到下标(注意类型匹配)。it == a + n
,此时不能访问 *it
;https://cspoj.com/contest.php?cid=1002Fus5yz4x3EcSJH1Z
注意事项
文件名(程序名和输入输出文件名)必须使用英文小写。(提交必须使用freopen()进行提交)
C/C++ 中函数 main() 的返回值类型必须是 int,程序正常结束时的返回值必须是0。
提交的程序代码文件的放置位置请参考各省的具体要求。
因违反以上三点而出现的错误或问题,申述时一律不予受理。
若无特殊说明,结果的比较方式为全文比较(过滤行末空格及文末回车)。
程序可使用的栈空间内存限制与题目的内存限制一致。
全国统一评测时采用的机器配置为:Inter® Core™ i7-8700K CPU @3.70GHz,内存 32GB。上述时限以此配置为准。
只提供 Linux 格式附加样例文件。
评测在当前最新公布的 NOI Linux 下进行,各语言的编译器版本以此为准
假设输入样例数据存在文件test.in中,输出样例数据存在文件test.out中,
则在CSP、NOI等比赛的代码中,需添加freopen、fclose语句,
内容详见模板代码如下。
#include <bits/stdc++.h>
#include<cstdio>//必须包含cstdio头文件
#include<iostream>
using namespace std;
int main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
cout<<"Hello NOI"<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
复制
下面为函数的简介,详细可参见 http://www.cplusplus.com/reference/clibrary/cstdio/freopen.html
函数名:freopen
声明:
FILE _freopen( const char_ path, const char _mode, FILE_ stream );
所在文件: stdio.h
参数说明:
path: 文件名,用于存储输入输出的自定义文件名。
mode: 文件打开的模式。和fopen中的模式(如r-只读, w-写)相同。
stream: 一个文件,通常使用标准流文件。
返回值:成功,则返回一个path所指定文件的指针;失败,返回NULL。(一般可以不使用它的返回值)
功能:实现重定向,把预定义的标准流文件定向到由path指定的文件中。标准流文件具体是指stdin、stdout和stderr。其中stdin是标准输入流,默认为键盘;stdout是标准输出流,默认为屏幕;stderr是标准错误流,一般把屏幕设为默认。通过调用freopen,就可以修改标准流文件的默认值,实现重定向。
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
freopen("7532.in", "r", stdin);
freopen("7532.out", "w", stdout);
//原来的代码保持不变
double a, b, r;
int k;
cin >> a >> b;
k = int(a/b);
r = a - b * k;
printf("%g", r);
//-------------
fclose(stdin);
fclose(stdout);
return 0;
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。