非常尴尬的是,我最近由于期末将近,各种无意义的作业接踵而来。所以day3在我的草稿本里难产而死,直接day4啦。
今天是二分查找的第一天
P1102 A-B 数对
还是一样,从基础题开始。这道题可以从简单的方面去想也可以使用STL库的函数,总之简单题多解吧。
题意
给一个N,C和有N个数字的数串,让我们寻找在串里有几个A,B对可以实现A-B=C。
我的解答:
#include <bits/stdc++.h>
#include <cstdio>
#define Max 101
using namespace std;
int n,c;
int num[200005];
int main(){
cin>> n >>c;
int cnt = 0;
for(int i = 0 ; i < n ; i ++){
cin >> num[i];
}
sort(num , num + n);
for(int i = n-1 ; i >= 0 ; i--){
for(int j = n-1 ; j >= 0; j--){
if(num[i] - num[j] > c) break;
else if(num[i] - num[j] == c){
cnt++;
}
else continue;
}
}
cout<<cnt<<endl;
return 0;
}
我本意的想法是排序后遍历两遍,如果出现了对于i有J-I>c了,那么就剪枝。
提交后,发现有三个样例TLS不通过,所以寻求更快的方式。
巧妙的暴力题解方式map
A-B=C那不就是A-C=B吗!!!!所以我们只需要利用输入控制即可!
其实也很容易就考虑到,如果对于输入后的数组,还是需要不断地遍历以寻求相等的那两个数的数量。所以!和数量有关,map上场!
题解复现:
#include <bits/stdc++.h>
#include <cstdio>
#define Max 101
using namespace std;
int n,c;
int num[200005];
map<int ,int >m;
int main(){
cin>> n >>c;
long long cnt = 0;
for(int i = 0 ; i < n ; i ++){
cin >> num[i];
m[num[i]]+=1;
num[i] -= c;
}
sort(num , num + n);
for(int i= 0; i<n;i++){
cnt += m[num[i]];
}
cout<<cnt<<endl;
return 0;
}
最后,对于cnt的范围,如果是200000个1与200000个2的话,最后cnt也是会爆int的。
因为本题用二分太过于。。傻逼了所以next one
P1678 烦恼的高考志愿
又是一道非常简单的题目,本着训练的目的,我准备必用二分来写~
写二分时,一定要弄清楚你要找的那个到底是第一个大于目标数的数还是小于or等于。
#include <bits/stdc++.h>
#include <cstdio>
#define Max 101
using namespace std;
int n,c;
int schooln[100005],studentn[100005];
map<int ,int >m;
int main(){
int school,student;
cin>> school >> student;
long long cnt = 0;
for(int i = 0 ; i < school ; i ++){
cin>> schooln[i];
}
for(int j = 0 ; j < student ; j ++){
cin>> studentn[j];
}
sort(schooln,schooln + school);
for(int i = 0 ; i < student ; i ++){
int j = 0,l = school-1;
while(j < l){
int mid = (j+l)/2;
if(schooln[mid] > studentn[i]){
l = mid;
}else{
j = mid+1;
}
}
if(studentn[i] < schooln[0]) cnt += schooln[0] - studentn[i];
// else cnt += abs(studentn[i] - schooln[l]);
else cnt += min(abs(studentn[i] - schooln[l]),abs(studentn[i] - schooln[l-1]));
}
cout<<cnt<<endl;
return 0;
}
!!!在迫不得已的时候再手写二分~我们有lower_bound和uppper_bound啊!!!
P2759 奇怪的函数
题意:我们需要找到一个数x,它的x次方是最先到达n位数字的结果的。输入为n(n<2000000000);因为x的x次方函数必是递增且我们要找的就是在这些里面第一个大于n的数,所以可以试一试二分。
x
x
≥
1
0
n
−
1
x^x \ge 10^{n-1}
xx≥10n−1
取对数后可以得到:
x
∗
lg
x
≥
n
−
1
x * \lg x \ge n-1
x∗lgx≥n−1
这个题碰到了一个非常无语的情况,一开始mid * log10(mid)判了两遍,直接TLS了。。。所以不写冗余代码很重要!
#include <bits/stdc++.h>
#include <cstdio>
#define Max 101
using namespace std;
int n,c;
map<int ,int >m;
int main(){
long long n;
cin>>n;
long long l = 0,h = n;
while(l <= h){
if(l == h){
cout<<l<<endl;
break;
}
long long mid = (h+l)/2;
if(mid * log10(mid) >= n-1){
h = mid;
}
else{
l = mid+1;
}
}
return 0;
}
咸鱼于2021年5月31日