#C241107A. [SDOI2009] HH的项链


#C241107A. [SDOI2009] HH的项链

标签(Label)

  • 莫队算法
  • 模板

网址(Website)

P1972 [SDOI2009] HH的项链 - 洛谷 (测试点太严格,但是作为模板还是不错)

【NOI模板】莫队算法 - HH的项链「SDOI2009」 - Super (数据水,可以过)

题目(Problem)

题目描述

HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,因此,他的项链变得越来越长。

有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答…… 因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。

输入格式

一行一个正整数 $n$,表示项链长度。
第二行 $n$ 个正整数 $a_i$,表示项链中第 $i$ 个贝壳的种类。

第三行一个整数 $m$,表示 HH 询问的个数。
接下来 $m$ 行,每行两个整数 $l,r$,表示询问的区间。

输出格式

输出 $m$ 行,每行一个整数,依次表示询问对应的答案。

样例 #1

样例输入 #1

6
1 2 3 4 3 5
3
1 2
3 5
2 6

样例输出 #1

2
2
4

提示

【数据范围】

对于 $20%$ 的数据,$1\le n,m\leq 5000$;
对于 $40%$ 的数据,$1\le n,m\leq 10^5$;
对于 $60%$ 的数据,$1\le n,m\leq 5\times 10^5$;
对于 $100%$ 的数据,$1\le n,m,a_i \leq 10^6$,$1\le l \le r \le n$。

本题可能需要较快的读入方式,最大数据点读入数据约 20MB

题解(Solution)

$\qquad$方法就是按 $\sqrt{n}$ 分块处理每一个询问,并且对于不在一个块的相邻询问按不同方法排序,然后暴力处理就好。

代码(Code)

#include<bits/stdc++.h>
#include<vector>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i--)
using namespace std;
#define P pair<int,int>
#define x first
#define y second
#define in(x,l,r) (l<=x && x<=r)
inline int rd(){
	char c;bool f=false;while(!isdigit(c=getchar()))f=c=='-';int x=c^48;
	while(isdigit(c=getchar())){x=(((x<<2)+x)<<1)+(c^48);}return f?-x:x;
}const int inf = 0x3f3f3f3f;
const int N = 1012345;
bool ST;

struct Wolf{int l,r,id;}b[N];
int pos[N];

int n,q,ans,a[N],as[N];

int cnt[N];
inline void add(int x){if(++cnt[x]==1) ans++;}
inline void del(int x){if(--cnt[x]==0) ans--;}

void Solve(){
	n=rd();int B = sqrt(n);
	For(i,1,n) a[i] = rd(), pos[i]=(i-1)/B+1;
	
	q=rd();For(i,1,q) b[i] = {rd(),rd(),i};
	
	sort(b+1,b+q+1,[&](Wolf a,Wolf b){
		if(pos[a.l]^pos[b.l]) return pos[a.l]<pos[b.l];
		if(pos[a.l] & 1) return a.r>b.r;
		return a.r<b.r;});
	
	int l=1,r=0;
	For(i,1,q){
		int L=b[i].l,R=b[i].r;
		while(l<L) del(a[l++]);
		while(r>R) del(a[r--]);
		while(l>L) add(a[--l]);
		while(r<R) add(a[++r]);
		as[b[i].id] = ans;
	}
	
	For(i,1,q) printf("%d\n",as[i]);
}

bool ED;
signed main(){
	cerr<<abs(&ST-&ED)/1024./1024.<<"MB\n";
	int T = 1;double Tim = clock();
	while(T--) Solve();
	return cerr<<"TIME:"<<(clock()-Tim)/CLOCKS_PER_SEC,0;
}

文章作者: WolfDeer
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WolfDeer !
  目录