zoukankan      html  css  js  c++  java
  • 浅谈主席树模板

    静态区间第k大
    没什么好说的,就是个模板
    但还是在代码里解释一下吧;

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int maxn =2e5;
    int tot,n,m;
    int sum[(maxn << 5) + 10],rt[maxn + 10],ls[(maxn << 5) + 10],rs[(maxn << 5) + 10];//数组要开到20倍!!!
    //rt[i]表示版本[1,i+1],
    //ls[]和rs[]分别表示其左儿子和右儿子,
    //sum[]表示当前在当前节点表示的区间内的个数
    int a[maxn + 10],ind[maxn + 10],len;
    inline int getid(const int &val){return lower_bound(ind + 1,ind + len + 1,val)-ind;}
    int build(int l,int r)
    {
        int root = ++tot;
        if(l == r)return root;
        int mid = l + r >> 1;
        ls[root] = build(l,mid);
        rs[root] = build(mid + 1,r);
        return root;
    }//bulid维护节点,返回节点
    int update(int k,int l,int r,int root)
    {
        int dir = ++tot;
        ls[dir] = ls[root],rs[dir] = rs[root],sum[dir] = sum[root] + 1;//跟新 新节点
        if(l == r)return dir;//和线段树一样,到了叶节点
        int mid = l + r >> 1;
        if(k <= mid)
            ls[dir] = update(k,l,mid,ls[dir]);
        else
            rs[dir] = update(k,mid + 1,r,rs[dir]);
        return dir;
    }//update维护节点,返回节点
    int query(int u,int v,int l,int r,int k)
    {
        int mid = l + r >> 1,x = sum[ls[v]] - sum[ls[u]];//前提:区间可减性,因为本题的特殊性,是维护前缀的版本,这个性质才得以实现,感性理解一下
        if(l == r)return l;
        if(k <= x)return query(ls[u],ls[v],l,mid,k);
        else return query(rs[u],rs[v],mid + 1,r,k - x);
    }//query维护下标
    inline void init()
    {
        scanf("%d%d",&n,&m);
        for(register int i = 1;i <= n;++i)
            scanf("%d",a + i);
        memcpy(ind,a,sizeof ind);
        sort(ind + 1,ind + n + 1);
        len = unique(ind + 1,ind + n + 1) - ind - 1;
        rt[0] = build(1,len);
        for(register int i = 1;i <= n;++i)
            rt[i] = update(getid(a[i]),1,len,rt[i - 1]);
    }
    int l,r,k;
    inline void work(){
        while(m--){scanf("%d%d%d",&l,&r,&k);
            printf("%d
    ",ind[query(rt[l - 1],rt[r],1,len,k)]);
        }
    }
    int main()
    {
        init();
        work();
        return 0;
    }
    
  • 相关阅读:
    Toolbar设置回退箭头的方法
    Android进程绝杀技--forceStop
    线程池的经典使用
    Handler+ExecutorService(线程池)+MessageQueue模式+缓存模式
    adb pull apk
    工厂模式_工厂方法模式
    工厂模式_简单工厂模式
    spring_aop
    代理模式_动态代理
    代理模式_静态代理
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/11600220.html
Copyright © 2011-2022 走看看