【AtCoder】离线询问+树状数组

D - AtCoder Express 2

题目描述

在这里插入图片描述

input#1

2 3 1
1 1
1 2
2 2
1 2

output#1

3

input#2

10 3 2
1 5
2 8
7 10
1 7
3 10

output#2

1
1

input#3

10 10 10
1 6
2 9
4 5
4 7
4 7
5 8
6 6
6 7
7 9
10 10
1 8
1 9
1 10
2 8
2 9
2 10
3 8
3 9
3 10
1 10

output#3

7
9
10
6
8
9
6
7
8
10


题意

给定 n ( ≤ 500 ) n(\leq500) n(500) m ( ≤ 2 e 5 ) m(\leq2e5) m(2e5) q ( ≤ 1 e 5 ) q(\leq1e5) q(1e5),然后输入 m m m 个在 [ 1 , n ] [1, n] [1,n] 内的闭区间 [ L , R ] [L, R] [L,R]
接下来输入 q q q 个询问,每个询问输入两个数表示闭区间 [ i , j ] [i, j] [i,j],对每个询问输出在 [ i , j ] [i, j] [i,j] 内的完整闭区间个数。

思路

如本文标题,我们需要对询问离线处理,这样对于区间询问,我们就可以进行排序,并使得左端点单调增,以便处理后续问题。

考虑用树状数组维护区间右端点,所以可以先将所有的区间的右端点加入树状数组中。在每次询问一个区间 [ l , r ] [l, r] [l,r] 时,删掉所有区间左端点小于 l l l 的树状数组中右端点的值。然后直接进行查询当前右端点小于等于 r r r 的值的个数,即位该询问的结果。

代码

class BIT {
public:
	BIT() { memset(tr, 0, sizeof tr); }
	int tr[N];
	void add(int x, int v = 1) { for (; x < N; x += x & -x) tr[x] += v; }
	int sum(int x) { int res = 0; for (; x; x -= x & -x) res += tr[x]; return res; }
};

int n, m, q;

struct node {
	int l, r;
	int id;
	bool operator<(const node &A) const {
		if (l == A.l) return r < A.r;
		return l < A.l;
	}
}; 

node a[N], b[N];
int res[N];

void solve() {
	cin >> n >> m >> q;
	BIT tree;
	for (int i = 1; i <= m; i++) {
		int l, r; cin >> l >> r;
		a[i] = {l, r};
		tree.add(r, 1);
	}
	for (int i = 1; i <= q; i++) {
		int l, r; cin >> l >> r;
		b[i] = {l, r, i}; 
	}
	sort(a + 1, a + 1 + m);
	sort(b + 1, b + 1 + q);
	int j = 1;
	for (int i = 1; i <= q; i++) {
		int l = b[i].l, r = b[i].r, id = b[i].id;
		while (j <= m && a[j].l < l) {
			tree.add(a[j].r, -1);
			j++;
		}
		res[id] = tree.sum(r);
	}
	for (int i = 1; i <= q; i++) {
		cout << res[i] << endl;
	}
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ღCauchyོꦿ࿐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值