其他分享
首页 > 其他分享> > 【Luogu P1972】HH的项链

【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;
} 

标签:return,int,Luogu,sum,1000005,HH,const,P1972
来源: https://www.cnblogs.com/notscience/p/11796568.html