很明显,元素k的起始位置就是第一个大于等于k的元素的下标,终止位置就是第一个大于k的元素的下标,所以用二分查找。
二分板子:【二分】
C++
题解一:手写二分函数
#include <bits/stdc++.h>
using namespace std;
int n, q, nums[100010];
int lower(int l, int r, int k) {
while (l < r) {
int mid = l + r >> 1;
if (nums[mid] >= k) r = mid;
else l = mid + 1;
}
return l;
}
int upper(int l, int r, int k) {
while (l < r) {
int mid = l + r + 1 >> 1;
if (nums[mid] <= k) l = mid;
else r = mid - 1;
}
}
int main()
{
scanf("%d %d", &n, &q);
for (auto i = 0; i < n; ++ i) scanf("%d", &nums[i]);
while (scanf("%d", &q) != EOF) {
int begin = lower(0, n - 1, q); // lower()函数查找首个大于q的元素
if (nums[begin] != q) printf("-1 -1\n"); // 未查找到或者仅存在大于不存在等于的元素
else {
int end = upper(0, n - 1, q); // upper()函数查找首个大于等于q的元素
printf("%d %d\n", begin, end); // 输出查找结果
}
}
}
题解二:数组 + upper_bound() + lower_bound()
#include <bits/stdc++.h>
using namespace std;
int n, q, nums[100010];
int main()
{
scanf("%d %d", &n, &q);
for (auto i = 0; i < n; ++ i) scanf("%d", &nums[i]);
while (scanf("%d", &q) != EOF) {
auto begin = lower_bound(nums, nums + n, q); // lower_bound()函数查找首个大于q的元素
auto end = upper_bound(nums, nums + n, q); // upper_bound()函数查找首个大于等于q的元素
if (*begin != q) cout << "-1 -1\n"; // 该元素不存在或者仅存在大于但是却不等于的元素
else cout << begin - nums << ' ' << end - nums - 1 << '\n'; // 输出查找结果
}
}
题解三:vector + upper_bound() + lower_bound()
#include <bits/stdc++.h>
using namespace std;
int n, q;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> q;
vector<int> nums(n);
for (auto i = 0; i < n; ++ i) cin >> nums[i];
while (cin >> q) {
auto begin = lower_bound(nums.begin(), nums.end(), q);
auto end = upper_bound(nums.begin(), nums.end(), q);
if (*begin != q) cout << "-1 -1\n";
// else cout << distance(nums.begin(), begin) << ' ' << distance(nums.begin(), end) - 1 << '\n';
else cout << begin - nums.begin() << ' ' << end - nums.begin() - 1 << '\n';
}
}