今天早上6点多醒过来自学树状数组,然后弄懂了这道题
树状数组 这个博客不错,讲的通俗易懂
思路:本来是一个数组从中间截断,很难想,但是换一种思路,将前面一段数组拼到后面,就成了在一段区间一段连续的数组求有多少个不同个数,之后就可以用树状数组求啦。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define Max int(2e5+10)
int n,p,a[Max],c[Max],resu[Max],vis[Max];
struct query
{
int l,r,pos;
}q[Max];
bool operator <(query x,query y)
{
return x.r<y.r;
}
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int d)
{
while(x<Max)
{
c[x]+=d;
x+=lowbit(x);
}
}
int sum(int x)
{
int su=0;
while(x>0)
{
su+=c[x];
x-=lowbit(x);
}
return su;
}
int main()
{
while(~scanf("%d%d",&n,&p))
{
memset(c,0,sizeof c);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[n+i]=a[i];
}
int l,r;
for(int i=1;i<=p;i++)
{
scanf("%d%d",&l,&r);
q[i].l=r;
q[i].r=l+n;
q[i].pos=i;
}
sort(q+1,q+1+p);
n*=2;
memset(vis,0,sizeof vis);
for(int i=1,j=1;i<=n&&j<=p;i++)
{
if(vis[a[i]])
add(vis[a[i]],-1);
add(i,1);
vis[a[i]]=i;
while(j<=p&&q[j].r<=i)
{
resu[q[j].pos]=sum(q[j].r)-sum(q[j].l-1);
j++;
}
}
for(int i=1;i<=p;i++)
printf("%d\n",resu[i]);
}
}