zoukankan      html  css  js  c++  java
  • 主席树-指针实现-找第k小数

    主席树,其实就是N颗线段树

    只是他们公用了一部分节点(๑•̀ㅂ•́)و✧

    我大部分的代码是从一位大佬的那里看到的

    我这个垃圾程序连Poj2104上的数据都过不了TLE

    so希望神犇能给我看看,

    顺便给和我一样的底层人物一点指针的帮助

    也许是 new 太慢了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define N 100100
    using namespace std;
    struct XDS{
        int l,r,dat;
        XDS *lc,*rc;
        XDS(){l=r=dat=0,lc=rc=NULL;}
    };XDS *ro[N];
    int n,qn,num[N],val[N],len;
    void prerun(){//这是离散化的预处理 
        sort(val+0,val+n);
        len=unique(val+0,val+n)-val;
    }
    int fvind(int x){//离散化get 
        return lower_bound(val+0,val+len,x)-val+1;
    }
    void Empty_total(XDS *&rt,int l,int r){//以l为左,r为右处理一颗空树,初始化 
        rt=new XDS();
        rt->l=l;
        rt->r=r;
        if(l==r)return ;
        int mid=(l+r)/2;
        Empty_total(rt->lc,l,mid);
        Empty_total(rt->rc,mid+1,r);
    }
    void dfs(XDS *rt){//调试用的,不用管
        if(rt==NULL)return;
        cout<<rt<<" "<<rt->l<<" "<<rt->r<<" "<<rt->dat<<"
    ";
        dfs(rt->lc);
        dfs(rt->rc);
    }
    void add(XDS *his,XDS *&nrt,int v){//his:从上一个转移过来,nrt :现在在搞的 (同位转移)增加一个|V:离散化后 
        if(his==NULL)return ;//结束 
        if(nrt==NULL)nrt=new XDS();//新开节点
        int l=his->l;nrt->l=l;
        int r=his->r;nrt->r=r;
        if(l==r){
            nrt->dat=his->dat+1;
            return ;
        }
        int mid=(l+r)/2;
        if(v<=mid){//值在左侧 
            nrt->rc=his->rc;//直接拿右侧 
            add(his->lc,nrt->lc,v);//查左 
        }
        else{//值在右侧 
            nrt->lc=his->lc;//直接拿左侧 
            add(his->rc,nrt->rc,v);//查右 
        }
        nrt->dat=nrt->lc->dat+nrt->rc->dat;
    }
    int query(XDS *lrt,XDS *rrt,int k){//在lrt与rrt之间查第K大 
        int l=1,r=len;//二分查找
        while(l<r){
            int mid=(l+r)/2;
            int cnt=rrt->lc->dat-lrt->lc->dat;/*两个树的左子树差
            即在这个区间内在[0,mid]范围内的增加值 */
            if(cnt>=k){//比k个多,往左搜 
                r=mid;
                lrt=lrt->lc;
                rrt=rrt->lc;//同步浏览 
            }
            else {//比k个少,往右 
                l=mid+1;
                k-=cnt;
                lrt=lrt->rc;
                rrt=rrt->rc;
            }
        }
        return l;
    }
    int main(){
        scanf("%d%d",&n,&qn);
        for(int i=1;i<=n;i++){
            scanf("%d",&num[i]);
            val[i-1]=num[i];
        }
        prerun(); 
        Empty_total(ro[0],1,len);
    //    dfs(ro[0]);
        for(int i=1;i<=n;i++){
            add(ro[i-1],ro[i],fvind(num[i]));
        }
        int a,b,c;
        for(int i=1;i<=qn;i++){
            scanf("%d%d%d",&a,&b,&c);
    //        cout<<query(ro[a-1],ro[b],c)<<endl;
            printf("%d
    ",val[query(ro[a-1],ro[b],c)-1]);
        }
        return 0;
    }
    
    Miemeng真的蒻
  • 相关阅读:
    [Install] TeamViewer
    [2017
    [2017 ACL] 对话系统
    [2018 ACL Short and System] 对话系统
    Git分支创建与合并
    Git常用命令
    JSONObject转换分析
    数据库行锁实现
    Jenkins安装
    Tomcat热部署,Web工程中线程没有终止
  • 原文地址:https://www.cnblogs.com/kalginamiemeng/p/11008306.html
Copyright © 2011-2022 走看看