zoukankan      html  css  js  c++  java
  • 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
    ",ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    P1067 多项式输出(模拟水题)
    A. The Fair Nut and Elevator(暴力)
    A. The Fair Nut and Elevator(暴力)
    Knight Tournament (set)
    jquery怎么添加多个类名
    jquery对类的操作,添加,删除,点击添加,再点击删除
    jquery操作css样式的方法
    jquery浅复制和深复制区别
    TS 三种函数的定义方式
    ES7及ES8新特性
  • 原文地址:https://www.cnblogs.com/wushengyang/p/12391320.html
Copyright © 2011-2022 走看看