Atcoder Beginner Contest 174F - Range Set Query解题报告

Atcoder Beginner Contest 174F - Range Set Query解题报告

1 题目链接

传送门

2 题目大意

题目:范围集合查询
题目大意:

问一个序列中 l l l r r r 中有多少个不同的数。

3 解法分析

如果没记错的话是在 2023 G D K O I 2023GDKOI 2023GDKOI 讲解过的。

将询问离线下来。

从左到右遍历数组,用树状数组存每种颜色出现的最右下标。

对于询问 ( l , r ) (l,r) (l,r),在遍历到 r r r 位置时,该询问的答案就是树状数组中 [ l , r ] [l,r] [l,r] 的和, 直接查询即可。

4 AC Code

#include
#define rep(i, a, b) for (int (i) = (a); (i) <= (b); ++(i))
#define fep(i, a, b) for (int (i) = (a); (i) < (b); ++(i))
#define int long long
#define N 500007
using namespace std;

int n, q;
int c[N], l[N], r[N];
int a[N], b[N], ans[N];
vector <pair <int, int> > x[N];

void add(int x,int v) {
	for (int i = x; i <= n; i += i & -i)
		b[i] += v;
}

int sum(int x) {
	int v = 0;
	for (int i = x; i > 0; i -= i & -i)
		v += b[i];
	return v;
}

signed main() {
	scanf("%lld%lld", &n, &q);
	rep(i, 1, n)
		scanf("%lld", &c[i]);
	rep(i, 1, q) {
		scanf("%lld%lld", &l[i], &r[i]);
		x[r[i]].push_back({l[i], i});
	}
	rep(i, 1, n) {
		if (a[c[i]])
			add(a[c[i]], -1);
		a[c[i]] = i;
		add(i, 1);
		for (pair <int, int> it : x[i])
			ans[it.second] = sum(i) - sum(it.first - 1);
	}
	rep(i, 1, q)
		printf("%lld\n", ans[i]);
	return 0;
}

你可能感兴趣的:(Atcoder,Beginner,Contest,数据结构,算法,数据结构,c++)