AcWing 2492. HH的项链 (基础莫队)

AcWing 2492. HH的项链
莫队求的是询问给定区间内不同的数字的个数,使用双指针遍历给定的区间,在这种情况下依然会超时,所以就对询问的区间按照分块(第二关键字是区间右端点)进行排序,这样就可以保证双指针不重复遍历,最大程度降低时间复杂度
只是总结一下大概思路,具体讲解还是听y总的吧

#include<bits/stdc++.h>

using namespace std;

const int N = 50010, M = 2e5 + 10, S = 1e6 + 10;

struct query{
	int id, l, r;
}q[M];  //记录询问 

int n, m;
int w[N];  //记录项链的值
int cnt[S];  //记录每个数出现的次数,能出现的数的范围是1~1e6 
int res;  //记录不同的数出现过的次数
int len;  //一块内元素的最小值 
int ans[S];

int get(int x){
	return x / len;
} 

bool cmp(query const& a, query const& b){
	int i = get(a.l), j = get(b.l);
	if(i != j) return i < j;
	return a.r < b.r;
} 

void add(int x, int &res){
	cnt[x] ++ ;
	if(cnt[x] == 1) res ++ ;
}

void del(int x, int &res){
	cnt[x] -- ;
	if(!cnt[x]) res -- ;
}

int main()
{
	cin>>n;
	for(int i = 1; i <= n; i ++ ){
		cin>>w[i];
	}

	cin>>m;
	len = max(1.0, sqrt((double)n * n / m));
	for(int i = 0; i < m; i ++ ){
		int a, b;
		cin>>a>>b;
		q[i] = {i, a, b};
	}
	
	sort(q, q + m, cmp);
	
	for(int k = 0, i = 0, j = 1, res = 0; k < m; k ++ ){  //res是一直要用的数,所以不用每次都重置为1 
		int id = q[k].id, l = q[k].l, r = q[k].r;
		//当r=6,i=3时,要考虑加入区间的数不包括w[3],所以是 ++ i 
		while(i < r) add(w[ ++ i], res);   
		//当i=6,r=3时,要考虑删除的数包括w[6],所以是i -- 
		while(i > r) del(w[i -- ], res);
		//当j=3,l=6时,要删除的数包括w[3],所以是j ++   
		while(j < l) del(w[j ++ ], res);
		//当j=6,l=3时,要考虑加入区间的数不包括w[6](因为已经在区间内),所以是 ++ i
		while(j > l) add(w[ -- j], res);
		ans[id] = res;
	}
	for(int i = 0; i < m; i ++ ) cout<<ans[i]<<endl;
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值