给你一个数组, 长度n<=1e5, q次询问(l, r), 输出区间[1, l], [r, n]中不同数字的个数, q<=1e5
莫队 简单粗暴:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct node{
int l,r,id;
}s[maxn];
int block[maxn],t,n,m;
int a[maxn],c[maxn],ans[maxn];
bool cmp(const node&a,const node &b)
{
if(block[a.l]==block[b.l]) return a.r<b.r;
return a.l<b.l;
}
int main()
{
//cout << "Hello world!" << endl;
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
int t=sqrt(n);
for(int i=1;i<=n;i++)
block[i]=(i-1)/t;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&s[i].l,&s[i].r);
s[i].id=i;
}
int l=0,r=n+1;
for(int i=1;i<=n;i++)
c[i]=0;
sort(s+1,s+m+1,cmp);
int num=0;
for(int i=1;i<=m;i++)
{
while(l<s[i].l)
{
l++;
c[a[l]]++;
if(c[a[l]]==1)
num++;
}
while(l>s[i].l)
{
c[a[l]]--;
if(c[a[l]]==0)
num--;
l--;
}
while(r>s[i].r)
{
r--;
c[a[r]]++;
if(c[a[r]]==1)
num++;
}
while(r<s[i].r)
{
c[a[r]]--;
if(c[a[r]]==0)
num--;
r++;
}
ans[s[i].id]=num;
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
return 0;
}
树状数组:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct node{
int l,r,id;
}s[maxn];
bool cmp(const node&a,const node&b)//右端点大的优先
{
if(a.r==b.r) return a.l<b.l;
return a.r>b.r;
}
int n,m,a[maxn],first[maxn],vis[maxn];
int sum[maxn];
int lowbit(int x){return x&-x;}
void update(int pos,int val)
{
while(pos<=n)
{
sum[pos]+=val;
pos+=lowbit(pos);
}
}
int query(int pos)
{
int ans=0;
while(pos>0)
{
ans+=sum[pos];
pos-=lowbit(pos);
}
return ans;
}
int pre[maxn],ans[maxn];
int main()
{
while(~scanf("%d%d",&n,&m))
{
memset(first,0,sizeof first);
int res=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(!first[a[i]])
{
first[a[i]]=i;
res++;
}
pre[i]=res;///记下i位置前面不同数的个数
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&s[i].l,&s[i].r);
s[i].id=i;
}
sort(s+1,s+m+1,cmp);
memset(sum,0,sizeof sum);
memset(vis,0,sizeof vis);
int l=0,r=n+1;
res=0;///从后往前遇到的不同数的个数
for(int i=1;i<=m;i++)
{
while(r>s[i].r)
{
r--;
if(!vis[a[r]])
{
res++;
vis[a[r]]=1;
update(first[a[r]],1);
}
}
ans[s[i].id]=pre[s[i].l]+res-query(s[i].l);//s[i].l以前不同数的个数+res-前后重复出现的数量
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
return 0;
}