SPOJ - DQUERY D-query —— 线段树 离线处理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lngxling/article/details/82145164

DQUERY - D-query

#sorting #tree

 
English Vietnamese

Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the number of distinct elements in the subsequence ai, ai+1, ..., aj.

Input

  • Line 1: n (1 ≤ n ≤ 30000).
  • Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 106).
  • Line 3: q (1 ≤ q ≤ 200000), the number of d-queries.
  • In the next q lines, each line contains 2 numbers i, j representing a d-query (1 ≤ i ≤ j ≤ n).

Output

  • For each d-query (i, j), print the number of distinct elements in the subsequence ai, ai+1, ..., aj in a single line.

Example

Input
5
1 1 2 1 3
3
1 5
2 4
3 5

Output
3
2
3 

题意:

问L到R区间内不一样的数有多少个

思路:

离线处理,按照询问的右节点排序,用map记录一下前面已经出现过的数,没当当前的数前面出现过,就在线段树中将前面的位置减1,当前的位置加1,这样就相当于把每个数后移到离当前询问最近的位置,然后在线段树中查询。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
struct node
{
	int l,r;
	int w;
};
struct node tree[120040];
struct qq
{
	int l,r;
	int id;
};
struct qq ques[200010];
bool cmp(const qq &a,const qq &b)
{
	return a.r<b.r;
}
int n,m;
int num[30010];
int ans[200010];
map<int,int>mp;
void built(int i,int l,int r)
{
	tree[i].l=l;
	tree[i].r=r;
	tree[i].w=0;
	if(l==r)
	return;
	int mid=(l+r)>>1;
	built(i<<1,l,mid);
	built(i<<1|1,mid+1,r);
}
void updata(int i,int x,int v)
{
	if(tree[i].l==tree[i].r)
	{
		tree[i].w+=v;
		return;
	}
	int mid=(tree[i].l+tree[i].r)>>1;
	if(x<=mid)
	updata(i<<1,x,v);
	else
	updata(i<<1|1,x,v);
	tree[i].w=tree[i<<1].w+tree[i<<1|1].w;
}
int query(int i,int l,int r)
{
	if(tree[i].l==l&&tree[i].r==r)
	{
		return tree[i].w;
	}
	int mid=(tree[i].l+tree[i].r)>>1;
	if(r<=mid)
	return query(i<<1,l,r);
	else if(l>mid)
	return query(i<<1|1,l,r);
	else
	return query(i<<1,l,mid)+query(i<<1|1,mid+1,r);
}
int main()
{
	mp.clear();
	scanf("%d",&n);
	built(1,1,n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&num[i]);
	}
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&ques[i].l,&ques[i].r);
		ques[i].id=i;
	}
	sort(ques+1,ques+1+m,cmp);
	int now=0;
	for(int i=1;i<=m;i++)
	{
		for(int j=now+1;j<=ques[i].r;j++)
		{
			if(mp[num[j]]!=0)
			{
				int k=mp[num[j]];
				updata(1,k,-1);
			}
			updata(1,j,1);
			mp[num[j]]=j;
		}
		ans[ques[i].id]=query(1,ques[i].l,ques[i].r);
		now=ques[i].r;
	}
	for(int i=1;i<=m;i++)
	printf("%d\n",ans[i]);
}

猜你喜欢

转载自blog.csdn.net/Lngxling/article/details/82145164