P1678题库链接:https://www.luogu.org/problem/P1678
难度:普及-
算法标签:模拟,贪心,排序,二分查找
1.朴素模拟 O(m*n) 得分30
先将m个学校的录取分数线排序,再用每名考生的成绩依次寻找第i个大学(若某个大学的录取分数线大于等于考生的成绩,即为第i个大学),该考生的成绩在第i-1个与第i个大学的录取分数线之间,用第i-1个和第i个大学的录取分数线分别减去该考生的成绩,取绝对值,因为要求出最小值,则用sum加上两者取绝对值后的较小值,最后sum即为答案
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 int m, n, a[100010], b[100010]; 5 int main() 6 { 7 scanf("%d%d", &m, &n); 8 int sum = 0; 9 for(int i = 0; i < m; ++i) 10 scanf("%d", &a[i]); 11 for(int i = 0; i < n; ++i) 12 scanf("%d", &b[i]); 13 sort(a, a + m); 14 for(int i = 0; i < n; ++i) 15 { 16 for(int j = 0; j < m; ++j) 17 { 18 if(b[i] <= a[j]) 19 { 20 if(j == 0) sum += a[0] - b[i]; 21 else sum += min(abs(a[j] - b[i]), abs(a[j - 1] - b[i])); 22 break; 23 } 24 } 25 } 26 printf("%d\n", sum); 27 return 0; 28 }
2.二分查找优化 O(log(m)*n) 得分100
利用二分查找来找到每名考生的第i个大学,其查找过程只需要log(m)次,可以解决时间复杂度较大的问题,其余与朴素算法同理
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 int m, n, a[100010], b[100010]; 5 int main() 6 { 7 scanf("%d%d", &m, &n); 8 int sum = 0; 9 for(int i = 0; i < m; ++i) 10 scanf("%d", &a[i]); 11 for(int i = 0; i < n; ++i) 12 scanf("%d", &b[i]); 13 sort(a, a + m); 14 for(int i = 0; i < n; ++i) 15 { 16 int l = 0, r = m - 1; 17 while(l < r) 18 { 19 int mid = (l + r) / 2; 20 if(b[i] >= a[mid]) l = mid + 1; 21 else if(b[i] < a[mid]) r = mid; 22 } 23 if(b[i] <= a[0]) sum += a[0] - b[i]; 24 else sum += min(abs(a[l - 1] - b[i]), abs(a[l] - b[i])); 25 } 26 printf("%d\n", sum); 27 return 0; 28 }