传送门1
传送门2
写在前面:信息课上的莫队练习
思路:比小Z的袜子还要简单些,不过BZOJ上4s的总时限确实把我吓了一跳
注意:种类编号为0-1000000,小心数组越界导致RE
代码:
#include"bits/stdc++.h"
using namespace std;
int m,n,tot,last_l=1,last_r;
int a[50010],block[50010],flag[1000001];
struct os
{
int l,r,num,ans;
}q[200010];
int cmp1(os x,os y)
{
if (block[x.l]<block[y.l]) return 1;
if (block[x.l]>block[y.l]) return 0;
return x.r<y.r;
}
int cmp2(os x,os y){return x.num<y.num;}
int in()
{
int f=1,t=0;
char ch=getchar();
while (ch>'9'||ch<'0')
{
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9') t=t*10+ch-'0',ch=getchar();
return f*t;
}
main()
{
n=in();
for (int i=1;i<=n;i++) a[i]=in();
block[0]=sqrt(n);
for (int i=1;i<=n;i++)
block[i]=(i-1)/block[0]+1;
m=in();
for (int i=1;i<=m;i++)
q[i].l=in(),
q[i].r=in(),
q[i].num=i;
sort(q+1,q+m+1,cmp1);
for (int i=1;i<=m;i++)
{
if (q[i].r>last_r)
for (int j=last_r+1;j<=q[i].r;j++)
{
if (!flag[a[j]]) tot++;
flag[a[j]]++;
}
if (q[i].r<last_r)
for (int j=last_r;j>q[i].r;j--)
{
flag[a[j]]--;
if (!flag[a[j]]) tot--;
}
if (q[i].l<last_l)
for (int j=last_l-1;j>=q[i].l;j--)
{
if (!flag[a[j]]) tot++;
flag[a[j]]++;
}
if (q[i].l>last_l)
for (int j=last_l;j<q[i].l;j++)
{
flag[a[j]]--;
if (!flag[a[j]]) tot--;
}
last_l=q[i].l;
last_r=q[i].r;
q[i].ans=tot;
}
sort(q+1,q+m+1,cmp2);
for (int i=1;i<=m;i++) printf("%d\n",q[i].ans);
}