HH的项链—树状数组

题目描述
HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。
HH不断地收集新的贝壳,因此他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?
这个问题很难回答。。。因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。

输入格式
第一行:一个整数N,表示项链的长度。
第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。
第三行:一个整数M,表示HH询问的个数。
接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。

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

样例
样例输入
6
1 2 3 4 3 5
3
1 2 
3 5
2 6
    
样例输出
2
2
4

数据范围与提示
N ≤ 50000,M ≤ 200000。

思路:

我做这道题的思路是树状数组+排序(只因博主没学过莫队),首先记录下每种贝壳的下一种不同贝壳所在的位置,将所有询问按照右端点进行排序。从左往右遍历,扫过一个元素就将该位置++,若有前驱,再将前驱--。遍历到区间端点答案为getsum[r]-getsum[l-1](getsum为前缀和)。

还有一点,本题的数据范围真的假,范围给到20万,样例中早已经超过这个范围,所以博主在REn次后才得出要开到100万才行(好好好,故意多给几个RE是吧)。

蒟蒻の代码:

#include <bits/stdc++.h>
using namespace std;
const int N=1000000;
int n,m,vis[N],c[N],a[N],ans[N];
struct node{
	int l,r,num;
}s[N];
bool cmp(node a,node b){
	return (a.r<b.r||(a.r==b.r&&a.l<b.l));
}
int lowbit(const int x){
	return x&-x;
}
void add(int x,int key){
	while(x<=n){
		c[x]+=key;
		x+=lowbit(x);
	}
}

int getsum(int x){
	int s=0;
	while(x>0){
		s+=c[x];
		x-=lowbit(x);
	} 
	return s;
}
int main(){
	int i,j;
	cin>>n;
	for(i=1;i<=n;i++) cin>>a[i];
	cin>>m;
	for(i=1;i<=m;i++){
		cin>>s[i].l>>s[i].r;
		s[i].num=i;
	}
	sort(s+1,s+1+m,cmp);
	j=1;
	for(i=1;i<=n+1;i++){
		while(j<=m&&i>s[j].r){
			ans[s[j].num]=getsum(s[j].r)-getsum(s[j].l-1);
			j++;
		}
	    if(i>n) break;
	    if(vis[a[i]]){
		    add(vis[a[i]],-1);
		    vis[a[i]]=i;
		    add(i,1);
	    }else{
		    vis[a[i]]=i;
		    add(i,1);
	    }
	}
	for(int i=1;i<=m;i++) 
	    cout<<ans[i]<<endl;
	return 0;
}

如有错误,欢迎大佬指正~

#一名爱打篮球的oier#

posted @ 2024-02-19 07:10  __kw  阅读(39)  评论(0)    收藏  举报