
二分查找与二分答案入门c++
比原来的二分多一步,即寻找第一次出现的位置,所以while循环中相等的情况需要额外判断是不是第一次。其实如果没有那两个return 0的语句会RE两个,作者也不知道怎么回事。给学校排序,根据学生的分数找学校(二分),直到找到小于等于学生分数的学校。a-b=c转化为a=b+c,找到所有的a使b+c=a。找a的时候用二分,可以拿92分(样例3TLE力)介绍两个非常好用的函数,方法和上面一样,详见注释。
·
目录
P2249 【深基13.例1】查找 - 洛谷 (luogu.com.cn)
P1102 A-B 数对 - 洛谷 (luogu.com.cn)
P1678 烦恼的高考志愿 - 洛谷 (luogu.com.cn)
P2440 木材加工 - 洛谷 (luogu.com.cn)
P2249 【深基13.例1】查找 - 洛谷 (luogu.com.cn)
比原来的二分多一步,即寻找第一次出现的位置,所以while循环中相等的情况需要额外判断是不是第一次。需要注意应该写while (left <= right)
#include<iostream>
#include<vector>
using namespace std;
int main() {
int n, m;
int t;
cin >> n >> m;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 0; i < m; i++) {
cin >> t;
int res = -1;
int left = 1;
int right = n;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (a[mid] > t) {
right = mid - 1;
}
else if (a[mid] < t) {
left = mid + 1;
}
else if (a[mid] == t) {
res = mid;
right = mid-1 ;
}
}
cout << res << " ";
}
return 0;
}
P1102 A-B 数对 - 洛谷 (luogu.com.cn)
a-b=c转化为a=b+c,找到所有的a使b+c=a
找a的时候用二分,可以拿92分(样例3TLE力)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
int n, c;
scanf("%d %d", &n, &c);
vector<int> a(n);
for (int i = 0; i < n; i++)cin >> a[i];
sort(a.begin(), a.end());
int res = 0;
//a-b=c转化为a=b+c
for (int i = 0; i < n; i++) {
int b = a[i];
//找到所有的a使b+c=a
int left = 0;
int right = n - 1;
int t = -1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (a[mid] > (b + c)) right = mid - 1;
else if (a[mid] < (b + c)) left = mid + 1;
else {
t = mid;
right = mid - 1;
}
}
if (t != -1) {
while (t < n && (a[t] == b + c)) {
res++;
t++;
}
}
}
printf("%d\n", res);
return 0;
}
介绍两个非常好用的函数,方法和上面一样,详见注释
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
int n, c;
scanf("%d %d", &n, &c);
vector<int> a(n);
for (int i = 0; i < n; i++)cin >> a[i];
sort(a.begin(), a.end());
int res = 0;
for (int i = 0; i < n; i++) {
res += upper_bound(a.begin(), a.end(), a[i] + c) - lower_bound(a.begin(), a.end(), a[i] + c);
//upper_bound:找到最后一个与a[i] + c相等的数
//lower_bound:找到第一个与a[i] + c相等的数
}
printf("%d\n", res);
return 0;
}
可惜还是过不去
原来是要开long long。。。。。。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
#define int long long
signed main() {
int n, c;
scanf("%lld %lld", &n, &c);
vector<int> a(n);
for (int i = 0; i < n; i++)cin >> a[i];
sort(a.begin(), a.end());
int res = 0;
for (int i = 0; i < n; i++) {
res += upper_bound(a.begin(), a.end(), a[i] + c) - lower_bound(a.begin(), a.end(), a[i] + c);
//upper_bound:找到最后一个与a[i] + c相等的数
//lower_bound:找到第一个与a[i] + c相等的数
}
printf("%lld\n", res);
return 0;
}
欧耶,过了过了过了!
P1678 烦恼的高考志愿 - 洛谷 (luogu.com.cn)
给学校排序,根据学生的分数找学校(二分),直到找到小于等于学生分数的学校
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
#define int long long
signed main() {
int m, n;
cin >> m >> n;
int res = 0;
vector<int> sch(m);
vector<int> stu(n);
for (int i = 0; i < m; i++)cin >> sch[i];
for (int i = 0; i < n; i++)cin >> stu[i];
sort(sch.begin(), sch.end());
for (int i = 0; i < n; i++) {
int left = 0;
int right = m - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (sch[mid] > stu[i])right = mid - 1;
else if (sch[mid] < stu[i]) {
if (mid + 1 == m) {
left = mid;
break;
}
else {
if (sch[mid + 1] > stu[i]) {
left = mid;
break;
}
else if (sch[mid + 1] == stu[i]) {
left = mid + 1;
break;
}
else left = mid + 1;
}
}
else {
left = mid;
break;
}
}
if (left != (m - 1)) {
int x = abs(sch[left] - stu[i]);
int y = abs(sch[left + 1] - stu[i]);
if (x > y)res += y;
else res += x;
}
else res += abs(sch[left] - stu[i]);
}
cout << res << endl;
return 0;
}
二分的时候看起来很麻烦,虽然还是AC了
P2440 木材加工 - 洛谷 (luogu.com.cn)
对切出来的最大值进行二分
#include<iostream>
#include<vector>
using namespace std;
#define int long long
signed main() {
int n, k;
cin >> n >> k;
vector<int> a(n);
int sum = 0;
int f = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
if (a[i] == 1)f = 1;
sum += a[i];
}
if (sum / k == 0) {
cout << 0 << endl;
return 0;
}
else {
if (f == 1) {
cout << 1 << endl;
return 0;
}
}
int left = 0;
int right = sum / k;
int res = 0;
while (left <= right) {
int mid = left + ((right - left) >> 1);
int count = 0;
for (int i = 0; i < n; i++) {
count += a[i] / mid;
}
if (count >= k) {
res = mid;
left = mid + 1;
}
else if (count<k) {
right = mid - 1;
}
}
cout << res << endl;
return 0;
}
其实如果没有那两个return 0的语句会RE两个,作者也不知道怎么回事。。。(可能是数据比较恶心)
更多推荐
所有评论(0)