P9426 [蓝桥杯 2023 国 B] 抓娃娃

P9426 [蓝桥杯 2023 国 B] 抓娃娃

一、问题简析

由题意,\(max\{r_i-l_i\}<=min\{R_i-L_i\}\),只要 \([l_i,r_i]\) 的中点在 \([L_i,R_i]\),则线段的一半肯定在区间中,即线段在区间中。我们可以先拿数组 A 存储各点处线段中点的个数,然后前缀和处理,得前缀和数组 psum,则区间 \([L_i,R_i]\) 包含中点的个数 psum[R] - psum[L - 1]

因为处理中点的坐标 \(\frac{l_i+r_i}{2}\) 存在小数,为了避免小数的出现,我们可以将中点坐标和区间范围都乘以 2

\[\begin{split} L_i&<=\frac{l_i+r_i}{2}<=R_i \\ 2L_i&<=l_i+r_i<=2R_i \end{split} \]

Code

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

ll quickin(void)
{
	ll ret = 0;
	bool flag = false;
	char ch = getchar();
	while (ch < '0' || ch > '9')
	{
		if (ch == '-')    flag = true;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9' && ch != EOF)
	{
		ret = ret * 10 + ch - '0';
		ch = getchar();
	}
	if (flag)    ret = -ret;
	return ret;
}

const int MAX =  2e6 + 10;
int A[MAX], psum[MAX], n, m;

int main()
{
	#ifdef LOCAL
	freopen("test.in", "r", stdin);
	#endif
	
	n = quickin(), m = quickin();
	for (int i = 0; i < n; ++i)
	{
		int a, b;
		a = quickin(), b = quickin();
		++A[a + b];
	}
	
	psum[1] = A[1];
	for (int i = 2; i < MAX; ++i)
		psum[i] = psum[i - 1] + A[i];
	
	for (int i = 0; i < m; ++i)
	{
		int a, b;
		a = quickin(), b = quickin();
		a *= 2, b *= 2;
		cout << psum[b] - psum[a - 1] << endl;
	}
	
	return 0;
}

posted @ 2024-05-12 21:13  ltign  阅读(36)  评论(0编辑  收藏  举报