OI学习,宁可不学不可逆向,要么知道题目怎么做后学习代码写法,要么知道代码基础学习题目怎么做,要么两种都会学习另外一种解法,万万不可逆向学习,费心费力。
P1678 烦恼的高考志愿
题目背景
计算机竞赛小组的神牛 V 神终于结束了高考,然而作为班长的他还不能闲下来,班主任老 t 给了他一个艰巨的任务:帮同学找出最合理的大学填报方案。可是 v 神太忙了,身后还有一群小姑娘等着和他约会,于是他想到了同为计算机竞赛小组的你,请你帮他完成这个艰巨的任务。
题目描述
现有 \(m\) 所学校,每所学校预计分数线是 \(a_i\)。有 \(n\) 位学生,估分分别为 \(b_i\)。
根据 \(n\) 位学生的估分情况,分别给每位学生推荐一所学校,要求学校的预计分数线和学生的估分相差最小(可高可低,毕竟是估分嘛),这个最小值为不满意度。求所有学生不满意度和的最小值。
输入格式
第一行读入两个整数 \(m,n\)。
第二行共有 \(m\) 个数,表示 \(m\) 个学校的预计录取分数。
第三行有 \(n\) 个数,表示 \(n\) 个学生的估分成绩。
输出格式
输出一行,为最小的不满度之和。
输入输出样例 #1
输入 #1
4 3
513 598 567 689
500 600 550
输出 #1
32
说明/提示
数据范围:
对于 \(30\%\) 的数据,\(1\leq n,m\leq10^3\),估分和录取线 \(\leq10^4\);
对于 \(100\%\) 的数据,\(1\leq n,m\leq10^5\),估分和录取线 \(\leq 10^6\) 且均为非负整数。
解析
这道题本身没有什么难度,重点看解法和手写二分
lower_bound解法
STL大好
#include<bits/stdc++.h>
using namespace std;
const int U=1e5+5;
int m,n;
long long a[U],b[U];
long long sum=0;
long long cnt=INT_MAX;
int main()
{#ifndef ONLINE_JUDGEfreopen("c.in","r",stdin);freopen("c.out","w",stdout);#endifcin>>m>>n;for(int i=1;i<=m;i++) cin>>a[i];sort(a+1,a+m+1);for(int j=1;j<=n;j++) cin>>b[j];for(int i=1;i<=n;i++){auto it=lower_bound(a+1,a+m+1,b[i]);int u=it-a;for(int j=u;j>=u-200&&j>=1;j--) cnt=min(cnt,abs(a[j]-b[i]));sum+=cnt;cnt=1e9;}cout<<sum<<endl;return 0;
}
// 编译常用指令>> g++ -std=c++14 -O2 -Wall code.cpp -o code
重头戏:手写二分
//手写二分
#include<bits/stdc++.h>
using namespace std;
const int U=1e5+5;
int m,n;
long long a[U],b[U];
long long sum=0;
long long cnt=INT_MAX;
#define mid ((L+R)/2)
int main()
{#ifndef ONLINE_JUDGEfreopen("c.in","r",stdin);freopen("c.out","w",stdout);#endifcin>>m>>n;for(int i=1;i<=m;i++) cin>>a[i];sort(a+1,a+m+1);for(int j=1;j<=n;j++) cin>>b[j];for(int i=1;i<=n;i++){int L=1,R=m;int ans=INT_MAX;while(L<=R){if(a[mid]==b[i]) {ans=0;break;}else if(a[mid]<b[i]){ans=min(ans,abs(int(a[mid]-b[i])) );L=mid+1;}else if(a[mid]>b[i]){ans=min(ans,abs(int(a[mid]-b[i])) );R=mid-1;}}sum+=ans;}cout<<sum<<endl;return 0;
}
// 编译常用指令>> g++ -std=c++14 -O2 -Wall code.cpp -o code
提炼一下模板
int L=1,R=m;答案初始化;while(L<=R){if(a[mid]==标准值) {答案处理;break;}else if(a[mid]<标准值){答案处理;L=mid+1;}else if(a[mid]>标准值){答案处理;R=mid-1;}}答案累加/答案处理;