luoguP1972 [SDOI2009]HH的项链

树状数组+排序。这种没有修改一眼就想到了离线。看了题解觉得挺神的。

但我想了想好像加个修改操作也可以,因为也可以按照修改操作顺序排序,

修改操作树状数组中只用 复原原来删的前面的数,删除修改的数。

#include<bits/stdc++.h>
using namespace std;
const int maxn=500010;
int n,m,c[maxn],a[maxn],re[maxn];
int book[1000010];
struct node{
    int x,y,num,ans;
}q[maxn];
int lowbit(int x){
    return x&-x;
}
void add(int x,int k){
    for(int i=x;i<=n;i+=lowbit(i)){
        c[i]+=k;
    }
}
int query(int x){
    int ret=0;
    for(int i=x;i>0;i-=lowbit(i)){
        ret+=c[i];
    }
    return ret;
}
bool cmp(const node&a,const node&b){
    return a.y<b.y;
}
bool cmp2(const node&a,const node&b){
    return a.num<b.num;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%d",&a[i]);
        a[i]++;
        if(!book[a[i]]){
            re[i]=-1;
        }
        else{
            re[i]=book[a[i]];
        }
        book[a[i]]=i;
    }
    scanf("%d",&m);
    for(int i=1;i<=m;++i){
        int x,y;
        scanf("%d%d",&x,&y);
        q[i].x=x;q[i].y=y;q[i].num=i;
    }
    sort(q+1,q+1+m,cmp);
    int j=1;
    for(int i=1;i<=n;++i){
        if(re[i]==-1){
            add(i,1);
        }
        else{
            add(re[i],-1);
            add(i,1);
        }
        for(;j<=m;++j){
            if(q[j].y==i){
                q[j].ans=query(i)-query(q[j].x-1);
            }
            else{
                break;
            }
        }
    }
    sort(q+1,q+1+m,cmp2);
    for(int i=1;i<=m;++i){
        printf("%d\n",q[i].ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Dream-Runner/p/9425113.html
今日推荐