• 1972 HH的项链


    传送门

    主席树解法
    设las[ i ]表示数列中第 i 个数的值 上一次出现的位置,num[ i ]为原数列中第 i 个数的值
    1. 把 从第 1 到第 i 个数的 las 的值  的出现次数 建立一个线段树
    那么第 i 个叶子节点 i 就表示 las 值为 i-1 的出现次数
    对于序列 1 2 1 3 4 1 建立的线段树如图:

    2. 一共有 n 个线段树,合在一起就是主席树(要对每个 i 建立线段树)

    3. 询问 l,r 就只要把第 r 个线段树中从 0 到 l-1 的值的和 减去第 l-1 个个线段树从 0 到 l-1 的值的和。


    关于第3点的证明:
    想一想,对于同一个 i , 第 r 个线段树的叶子节点 i 减去第 l-1 个线段树的叶子节点 i 的值( i 从 0 到 l-1) 就表示从 l~r 区间多出了的   区间  l~r (注意是从 l 到 r ) 中第一次出现的数字 a (a 为 num[ i ])的数量(多出的数量为 1 或 0,除非 i 等于 0)

    因为如果区间 l~r 中第 j 个数 a 再次出现(再次出现意思是数列 l~r 中已经有出现过 a 了),那么las[ j ]就为 区间l~r 中 的前面同一个数 a 的位置(显然 l<= las[ j ] <= r),不会更新叶子节点i的值(因为 0<= i <= l-1),因此可以把叶子节点的值拿来相减,既然叶子可以相减,那么它们的父节点也能相减.


    思路懂了就不难了..

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    const int N=500007;
    int n,m,cnt;
    int las[N],pre[N];
    
    
    //------以下为主席树------
    
    int rt[N],L[N<<8],R[N<<8],sum[N<<8];
    inline int build(int pre,int l,int r,int v)
    {
        int root=++cnt; sum[root]=sum[pre]+1;
        if(l==r) return root;
        L[root]=L[pre]; R[root]=R[pre];
        int mid=(l+r)>>1;
        if(v<=mid) L[root]=build(L[pre],l,mid,v);
        else R[root]=build(R[pre],mid+1,r,v);
        return root;
    }
    inline int query(int hea,int las,int l,int r,int ql)
    {
        if(r<=ql) return sum[las]-sum[hea];
        int mid=(l+r)>>1;
        int res=query(L[hea],L[las],l,mid,ql);
        return mid>=ql ? res : res+query(R[hea],R[las],mid+1,r,ql);
    }
    
    
    //------以上为主席树------
    
    int main()
    {
        int a;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            las[i]=pre[a];
            pre[a]=i;
        }
        for(int i=1;i<=n;i++)
            rt[i]=build(rt[i-1],0,n,las[i]);//注意l从0开始
        cin>>m;
        int l,r;
        while(m--)
        {
            scanf("%d%d",&l,&r);
            printf("%d
    ",query(rt[l-1],rt[r],0,n,l-1));//注意l从0开始
        }
        return 0;
    }
  • 相关阅读:
    POJ 1320 Street Numbers(佩尔方程)
    hdu 3292 No more tricks, Mr Nanguo
    佩尔方程
    hdu 4825 xor sum(字典树+位运算)
    Xor Sum 2(位运算)
    数串
    EJS
    JQuery性能优化
    常用正则
    JavaScript prototype继承中的问题
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9506789.html
Copyright © 2020-2023  润新知