SPOJ 3267

https://vjudge.net/problem/SPOJ-DQUERY

求区间内不重复的数的个数。

扫描数列建立可持久化线段树,第i个数若第一次出现,则在线段树中的位置i加1;若不是第一次出现,将上次出现的位置减1,在本次位置加1。

对于每个询问的区间 [L,R],在第R个版本上的线段树只有前R个数,在线段树上查询位置L,对经过的区间中的和进行累计即可。


#include<bits/stdc++.h>
using namespace std;
const int maxn=100001;
struct Node{
    int ls,rs;
    int cnt;
}tr[maxn*20];
int cur,rt[maxn];
void init(){
    cur=0;
}
inline void push_up(int o){
    tr[o].cnt=tr[tr[o].ls].cnt+tr[tr[o].rs].cnt;
}
int build(int l,int r){
    int k=cur++;
    if (l==r) {
        tr[k].cnt=0;
        return k;
    }
    int mid=(l+r)>>1;
    tr[k].ls=build(l,mid);
    tr[k].rs=build(mid+1,r);
    push_up(k);
    return k;
}
int update(int o,int l,int r,int pos,int val){
    int k=cur++;
    tr[k]=tr[o];
    if (l==pos&&r==pos){
        tr[k].cnt+=val;
        return k;
    }
    int mid=(l+r)>>1;
    if (pos<=mid) tr[k].ls=update(tr[o].ls,l,mid,pos,val);
    else tr[k].rs=update(tr[o].rs,mid+1,r,pos,val);
    push_up(k);
    return k;
}
int query(int l,int r,int o,int pos){
    if (l==r) return tr[o].cnt;
    int mid=(l+r)>>1;
    if (pos<=mid) return tr[tr[o].rs].cnt+query(l,mid,tr[o].ls,pos);
    else return query(mid+1,r,tr[o].rs,pos);
}
int b[maxn];
map<int,int> mp;
int main()
{
    int n,m;
    //int T;
    //scanf("%d",&T);
    //while (T--){
    while (~scanf("%d",&n)){
        mp.clear();
        init();
        for (int i=1;i<=n;i++){
            scanf("%d",&b[i]);
        }
        rt[0]=build(1,n);
        for (int i=1;i<=n;i++){
            if (mp.find(b[i])==mp.end()){
                mp[b[i]]=i;
                rt[i]=update(rt[i-1],1,n,i,1);
            }
            else{
                int tmp=update(rt[i-1],1,n,mp[b[i]],-1);
                rt[i]=update(tmp,1,n,i,1);
            }
            mp[b[i]]=i;
        }
        scanf("%d",&m);
        for (int i=0;i<m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            int ans=query(1,n,rt[b],a);
            printf("%d\n",ans);
        }
    }
    return 0;
}

 

posted @ 2020-03-01 18:58  wushuyng  阅读(109)  评论(0编辑  收藏  举报