【题目描述】
宠物狗旺财躲在数轴上的某处。小H收到到了 𝑁 条信息,每条信息是下面种之一:
● <= 𝑥:表示旺财躲在小于或等于 𝑥 的某个位置。
● >= 𝑥:表示旺财躲在大于或等于 𝑥 的某个位置。
不幸的是,这些信息不一定都正确,现在需要你帮助小H统计错误信息的最小数量。
【输入格式】
输入的第一行包含 𝑁。
以下 𝑁 行每行包含一条信息,格式见题目描述。
【输出格式】
输出错误信息的最小数量。
【输入输出样例】
Input
6
>= 3
<= 7
<= 5
>= 6
>= 8
<= 4
Output
2
【题解】
设 x[1]..x[n] 读入n条信息的x,也是旺财藏身的所有可能的位置
设 a[1]..a[na] 表示说 >=x 的数据,
设 b[1]..b[na] 表示说 <=x 的数据,
100分解法:排序+枚举+查找算法:
1)、将3个数组均由小到大排序;
2)、枚举旺财可能藏身的位置:x[1],x[2],……x[n]
● 假设狗藏在 x[k] 这个位置,则按下面方法计算此时错误信息数:
● 在a[1]..a[na]中查找有多少个元素大于x[k],假设有s1个(不正确数);
● 在b[1]..b[nb]中查找有多少个元素小于x[k],假设有s2个(不正确数);
●所以Ans=min(Ans,s1+s2)
至于查找:可以用二分查找,也可以利用单调性,用不回头顺序查找优化!
时间复杂度:
不回头顺序查找:O(n+n)
二分查找:O(nlogn)
【Code】
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 10;
int n,x[MAXN],a[MAXN],b[MAXN],na,nb,ans = 10000000;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n;
for(int i = 1;i <= n;i++){
string s;
int y;
cin >> s >> y;
x[i] = y;
if(s == ">="){
na++;
a[na] = y;
}
if(s == "<="){
nb++;
b[nb] = y;
}
}
sort(x + 1,x + 1 + n);
sort(a + 1,a + 1 + na);
sort(b + 1,b + 1 + nb);
for(int i = 1;i <= n;i++){
int p = upper_bound(a + 1,a + 1 + na,x[i]) - a;
int s1 = na - p + 1;
p = lower_bound(b + 1,b + 1 + nb,x[i]) - b;
int s2 = p - 1;
ans = min(ans,s1 + s2);
}
cout << ans;
return 0;
}
【补充知识——C++二分查找函数】
【upper_bound】
upper_bound
是 C++ 标准库中的一个函数模板,它定义在 <algorithm>
头文件中。这个函数用于在一个已排序的范围内查找第一个大于给定值的元素。如果所有元素都不大于给定值,则返回范围的结束迭代器。
具体来说,upper_bound
接收四个参数:前两个参数指定了要搜索的范围(开始迭代器和结束迭代器),第三个参数是要查找的值,而第四个参数(可选)是比较函数,用于确定元素是否应该被认为在查找的值之前(默认为小于)。
函数返回的是一个迭代器,指向第一个大于给定值的元素,如果所有元素都不大于给定值,则返回范围的结束迭代器。
以下是该函数的函数签名(C++20前)
template< class ForwardIt, class T >
ForwardIt upper_bound( ForwardIt first, ForwardIt last, const T& value );
例子:
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> v = {1, 2, 4, 4, 5, 6};
// 查找第一个大于4的元素
auto it = std::upper_bound(v.begin(), v.end(), 4);
if (it != v.end()) {
std::cout << "The first element greater than 4 is " << *it << std::endl;
} else {
std::cout << "No element is greater than 4" << std::endl;
}
return 0;
}
在这个例子中,upper_bound
将返回指向元素 5
的迭代器,因为它是范围内第一个大于 4
的元素。
【lower_bound】
lower_bound
是 C++ 标准库中的一个函数模板,它定义在 <algorithm>
头文件中。这个函数用于在一个已排序的范围内查找第一个不小于(即大于等于)给定值的元素。如果所有元素都小于给定值,则返回范围的结束迭代器。
函数签名通常如下所示:
template< class ForwardIt, class T >
ForwardIt lower_bound( ForwardIt first, ForwardIt last, const T& value );
例子:
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> v = {1, 2, 4, 4, 5, 6};
// 查找第一个不小于4的元素
auto it = std::lower_bound(v.begin(), v.end(), 4);
if (it != v.end()) {
std::cout << "The first element not less than 4 is " << *it << std::endl;
} else {
std::cout << "No element is not less than 4" << std::endl; // 这行实际上永远不会执行,因为v中至少有一个元素不小于4
}
// 输出将是 "The first element not less than 4 is 4"
return 0;
}
完结撒花!
特别鸣谢:文心一言