抓娃娃(蓝桥杯 2023 国赛 17110)
赛上写这道题时很快,看到区间和就想到前缀和,但对于抓取的判定,有点模糊,想是区间只刚好覆盖到中点,要做个特判。
赛后:
赛时的问题在数据范围已经被解决,即题目保证
max
{
r
i
−
l
i
}
≤
min
{
R
i
−
L
i
}
\max \{r_i - l_i\} \le \min \{R_i - L_i\}
max{ri−li}≤min{Ri−Li},翻译一下就是保证每个区间都可以完整地覆盖一条线段。
因为对于线段而言,只要至少一半的长度被包含则就会被某个区间框柱,那么,也就是说,只要包含其中一个端点和这个线段的中点即可。
因此,将所有线段按照中点位置从小到大排序,然后,对于每一个查询的区间,用前缀和计算该区间包含的线段数量。
当然,除了用前缀和的方法,也可以使用二分来进行计算。
Code:
/*
忽略每条线段,取而代之的是他们的中点
前缀和(线段树doge)
TODO
*/
#include <bits/stdc++.h>
using namespace std;
int n, m;
int sum[2000010];
int main() {
// freopen("catch.in","r",stdin);
// freopen("catch.out","w",stdout);
cin >> n >> m;
int l, r;
for (int i = 1; i <= n; i++) {
cin >> l >> r;
int mid = l + r;
//记录线段中点坐标(用于判断是否在区间内)
sum[mid]++;
}
for (int i = 1; i <= 1000010; i++) {
sum[i] += sum[i - 1];
}
int L, R;
for (int i = 1; i <= m; i++) {
cin >> L >> R;
L *= 2, R *= 2;
cout << sum[R] - sum[L - 1] << endl;
}
return 0;
}