【bzoj1878】统计区间不同种类数

本文介绍了一种区间查询问题的高效解决方法,适用于种类数量不大于60的情况。通过使用线段树进行维护,并将种类转化为二进制表示,实现快速查询区间内元素种类数。此外还提供了一种离线处理策略。

在线做法(只面对kind_num ≤ 60):

使用线段树维护,把种类压成一个二进制,每次pushup取或就可以了。

离线做法:见代码或他人题解!不会说!

#include <cstdio>
#include <algorithm>
using namespace std;
inline char gc() {
	static char now[1<<16], *S, *T;
	if(S == T) {T = (S = now) + fread(now, 1, 1<<16, stdin); if(S == T) return EOF;}
	return *S++;
}
inline int read() {
	int x = 0; char c = gc();
	while(c < '0' || c > '9') c = gc();
	while(c >= '0' && c <= '9') {x = x * 10 + c - 48; c = gc();}
	return x;
}
struct Query {int l, r, id;}q[200010];
int a[50010], pos[1000010], las[50010], BIT[50010], ans[200010];
int n, m;
inline bool cmp(Query A, Query B) {return A.r < B.r;}
inline void add(int x, int v) {for(; x <= n; x+= x & -x) BIT[x]+= v;}
inline int query(int x) {int ret = 0; for(; x; x-= x & -x) ret+= BIT[x]; return ret;}
int main() {
	n = read(); for(int i = 1; i <= n; ++i) a[i] = read();
	for(int i = 1; i <= n; ++i) las[i] = pos[a[i]], pos[a[i]] = i;
	m = read();
	for(int i = 1; i <= m; ++i) {q[i].l = read(); q[i].r = read(); q[i].id = i;}
	sort(q+1, q+m+1, cmp); int cur = 0;
	for(int i = 1; i <= m; ++i) {
		while(cur < q[i].r) {
			++cur;
			add(cur, 1); if(las[cur]) add(las[cur], -1);
		}
		ans[q[i].id] = query(q[i].r) - query(q[i].l - 1);
	}
	for(int i = 1; i <= m; ++i) printf("%d\n", ans[i]);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值