【Luogu P1972】HH的项链
Luogu P1972
一开始非常naive随便打了个树状数组统计就交上去了,然后不出意料的爆零了……
然后删一删改一改过了。
重点:对于区间[1,r]中重复出现的数,我们只需要关心最右边那一个是否在[l,r]中就可以了。
具体思路在代码注释中
#include<cstdio>
#include<algorithm>
using namespace std;
int n,c[1000005],a[1000005],check[1000005],m,maxi,ans[1000005];
struct data
{
int l,r,id;
bool operator < (const data&a) const&
{
return a.r>r;
}//重载运算符,使询问的区间r从小到大排序
}q[1000005];
int lowbit(int x)
{
return x&-x;
}
void add(int x,int num)
{
while (x<=n)
{
c[x]+=num;
x+=lowbit(x);
}
}
int query(int x)
{
int sum=0;
while (x>0)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
//树状数组基本操作,不再赘述。
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;//离线操作
}
sort(q+1,q+1+m);
int tmp=1;
for (int i=1;i<=m;i++)
{
for (int j=tmp;j<=q[i].r;j++)
{
if (check[a[j]]) add(check[a[j]],-1);//去掉之前打的标记,避免重复
add(j,1);
check[a[j]]=j;
//check[a[i]]数组用于记录a[i]在区间[1,r]中最后的位置
}
tmp=q[i].r+1;
ans[q[i].id]=query(q[i].r)-query(q[i].l-1);
}
for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}