zoukankan      html  css  js  c++  java
  • 静态区间第k大 树套树解法

    然而过不去你谷的模板

    思路:
    值域线段树([l,r])代表一棵值域在([l,r])范围内的点构成的一颗平衡树

    平衡树的(BST)权值为点在序列中的位置

    查询区间第(k)大值时

    左区间在([l,r])范围内的树的大小与(k)比较

    大了进去,小了减掉换一边

    关于建树

    递归建估计是(O(nlog^2n))


    Code:

    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    const int N=1e5+10;
    int ch[N*20][2],val[N*20],siz[N*20],pos[N*20],root[N<<2],tot;
    #define ls ch[now][0]
    #define rs ch[now][1]
    int n,m,n_,a[N],b[N];
    void updata(int now){siz[now]=siz[ls]+siz[rs]+1;}
    void split(int now,int k,int &x,int &y)
    {
        if(!now) {x=y=0;return;}
        if(pos[now]<=k)
            x=now,split(rs,k,rs,y);
        else
            y=now,split(ls,k,x,ls);
        updata(now);
    }
    int Merge(int x,int y)
    {
        if(!x||!y) return x+y;
        if(val[x]<val[y])
        {
            ch[x][1]=Merge(ch[x][1],y);
            updata(x);
            return x;
        }
        else
        {
            ch[y][0]=Merge(x,ch[y][0]);
            updata(y);
            return y;
        }
    }
    int New(int k)
    {
        val[++tot]=rand(),pos[tot]=k,siz[tot]=1;
        return tot;
    }
    void Insert(int id,int k)
    {
        int x,y;
        split(root[id],k,x,y);
        root[id]=Merge(x,Merge(New(k),y));
    }
    int ask(int id,int l,int r)//询问区间
    {
        int x,y,z,s;
        split(root[id],r,x,y);
        split(x,l-1,x,z);
        s=siz[z];
        root[id]=Merge(x,Merge(z,y));
        return s;
    }
    std::vector <int> loc[N];
    void build(int id,int l,int r)
    {
        if(l==r)
        {
            for(int i=0;i<loc[l].size();i++)
                Insert(id,loc[l][i]);
            return;
        }
        int mid=l+r>>1;
        build(id<<1,l,mid);
        build(id<<1|1,mid+1,r);
        for(int i=l;i<=r;i++)
            for(int j=0;j<loc[i].size();j++)
                Insert(id,loc[i][j]);
    }
    int query(int id,int l,int r,int ql,int qr,int k)
    {
        if(l==r) return a[l];
        int mid=l+r>>1,cnt;
        if((cnt=ask(id<<1,ql,qr))>=k)
            return query(id<<1,l,mid,ql,qr,k);
        else
            return query(id<<1|1,mid+1,r,ql,qr,k-cnt);
    }
    void init()
    {
        scanf("%d%d",&n_,&m);
        for(int i=1;i<=n_;i++) scanf("%d",a+i),b[i]=a[i];
        std::sort(a+1,a+1+n_);
        n=std::unique(a+1,a+1+n_)-a-1;
        for(int i=1;i<=n_;i++)
            loc[std::lower_bound(a+1,a+1+n,b[i])-a].push_back(i);
        build(1,1,n);
    }
    void work()
    {
        for(int l,r,k,i=1;i<=m;i++)
        {
            scanf("%d%d%d",&l,&r,&k);
            printf("%d
    ",query(1,1,n,l,r,k));
        }
    }
    int main()
    {
        init(),work();
        return 0;
    }
    
    

    2018.9.2

  • 相关阅读:
    Android开发:关于WebView
    PHP+JQUEY+AJAX实现分页
    Bootstrap入门(二)栅格
    BootStrap入门教程 (一)
    mac 终端命令
    没有功能需求设计文档?对不起,拒绝开发!
    React 入门教程
    Webpack+React+ES6开发模式入门指南
    webpack2.0+ vue2.0
    一个小时学会jQuery
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9575675.html
Copyright © 2011-2022 走看看