zoukankan      html  css  js  c++  java
  • 区间第k大

     归并树:

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    #include<map>
    #include<cmath>
    #include<set>
    #include<stack>
    #define ll long long
    #define max(x,y) (x)>(y)?(x):(y)
    #define min(x,y) (x)>(y)?(y):(x)
    #define cls(name,x) memset(name,x,sizeof(name))
    using namespace std;
    const int inf=1<<28;
    const int maxn=50010;
    const int maxm=110;
    const int mod=1e9+7;
    const double pi=acos(-1.0);
    int n;
    struct node
    {
        int *num;
        int len;
    }tree[maxn*4];
    int num[maxn];
    void build(int l,int r,int x)
    {
        tree[x].len=r-l+1;
        tree[x].num=new int[tree[x].len];
        if(l==r)
        {
            tree[x].num[0]=num[l];
            return ;
        }
        int mid=(l+r)/2;
        build(l,mid,x*2);
        build(mid+1,r,x*2+1);
        int i=0,j=0,k=0;
        while(i<tree[x*2].len&&j<tree[x*2+1].len)
        {
            if(tree[x*2].num[i]<tree[x*2+1].num[j])
                tree[x].num[k++]=tree[x*2].num[i++];
            else
                tree[x].num[k++]=tree[x*2+1].num[j++];
        }
        while(i<tree[x*2].len)
            tree[x].num[k++]=tree[x*2].num[i++];
        while(j<tree[x*2+1].len)
            tree[x].num[k++]=tree[x*2+1].num[j++];
    }
    int querry(int ql,int qr,int temp,int l,int r,int x)
    {
        if(ql==l&&qr==r)
        {
            int tl=0,tr=tree[x].len;
            while(tl<tr)
            {
                int mm=(tl+tr)/2;
                if(tree[x].num[mm]<temp)
                    tl=mm+1;
                else
                    tr=mm;
            }
            return tl;
        }
        int mid=(l+r)/2;
        if(qr<=mid)
            return querry(ql,qr,temp,l,mid,x*2);
        else if(ql>=mid+1)
            return querry(ql,qr,temp,mid+1,r,x*2+1);
        else
            return querry(ql,mid,temp,l,mid,x*2)+querry(mid+1,qr,temp,mid+1,r,x*2+1);
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(~scanf("%d",&n))
        {
            for(int i=1;i<=n;i++)
                scanf("%d",&num[i]);
            build(1,n,1);
            int q;
            scanf("%d",&q);
            while(q--)
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);//k有b-a-c个小于它的数
                int l=1,r=n;
                while(l<r)
                {
                    int mid=(l+r)/2;
                    int qc=querry(a+1,b+1,tree[1].num[mid],1,n,1);
                    if(qc<=b-a-c+1)
                        l=mid;
                    else
                        r=mid;
                    if(l+1==r) break;
                }
                if(querry(a+1,b+1,tree[1].num[r],1,n,1)==b-a-c+1)
                    printf("%d
    ",tree[1].num[r]);
                else
                    printf("%d
    ",tree[1].num[l]);
            }
        }
        return 0;
    }

    划分树:

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    #include<map>
    #include<cmath>
    #include<set>
    #include<stack>
    #define ll long long
    #define pb push_back
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)>(y)?(y):(x))
    #define cls(name,x) memset(name,x,sizeof(name))
    #define fs first
    #define sc second
    #define mp make_pair
    #define L(x) (1<<x)
    #define next Next
    using namespace std;
    const int inf=1e9+10;
    const ll llinf=1e16+10;
    const int maxn=4e5+10;
    const int maxm=1e3+10;
    const int mod=1e9+7;
    int n,m;
    struct node
    {
        int *num;
        int *c;//[l,i]有多少个数进入左子树
    }tree[maxn*4];
    int sorted[maxn];
    void init(int l,int r,int x)
    {
        tree[x].num=new int[r-l+2];
        tree[x].c=new int[r-l+2];
        tree[x].c[0]=0;
        if(l==r) return ;
        int mid=(l+r)/2;
        init(l,mid,x*2);
        init(mid+1,r,x*2+1);
    }
    void build(int l,int r,int x)//必须是稳定的快排
    {
        if(l==r) return ;
        int mid=(l+r)/2;
        int key=sorted[mid];
        int k1=0,k2=0;//进入左右子树的数量
        int c=0;//小于key必进入左子树数量
        for(int i=1;i<=r-l+1;i++)
            if(tree[x].num[i]<key) c++;
        c=mid-l+1-c;//等于key可进入左子树数量
        for(int i=1;i<=r-l+1;i++)
        {
            if(tree[x].num[i]<key)
                tree[x*2].num[1+k1++]=tree[x].num[i];
            else if(tree[x].num[i]==key)
            {
                if(c)
                {
                    tree[x*2].num[1+k1++]=tree[x].num[i];
                    c--;
                }
                else tree[x*2+1].num[1+k2++]=tree[x].num[i];
            }
            else tree[x*2+1].num[1+k2++]=tree[x].num[i];
            tree[x].c[i]=k1;
        }
        build(l,mid,x*2);
        build(mid+1,r,x*2+1);
    }
    int query(int ql,int qr,int k,int l,int r,int x)//返回[ql,qr]第k小的数
    {
        if(l==r)
            return tree[x].num[1];
        int cl=tree[x].c[qr-l+1]-tree[x].c[ql-1-l+1];//[ql,qr]中有多少进入了左子树
        int cr=qr-ql+1-cl;//[ql,qr]中有多少进入了右子树
        int mid=(l+r)/2;
        int tl=tree[x].c[ql-1-l+1]-tree[x].c[l-1-l+1];//[l,ql-1]中有多少进入了左子树
        int tr=ql-1-l+1-tl;//[l,ql-1]中有多少进入了右子树
        if(k<=cl)
            return query(l+tl,l+tl+cl-1,k,l,mid,x*2);
        else
            return query(mid+1+tr,mid+1+tr+cr-1,k-cl,mid+1,r,x*2+1);
    }
    int cquery(int ql,int qr,int k,int l,int r,int x)//返回[ql,qr]小于等于k的数量
    {
        if(l==r)
        {
            if(tree[x].num[1]<=k) return 1;
            else return 0;
        }
        int cl=tree[x].c[qr-l+1]-tree[x].c[ql-1-l+1];//[ql,qr]中有多少进入了左子树
        int cr=qr-ql+1-cl;//[ql,qr]中有多少进入了右子树
        int mid=(l+r)/2;
        int tl=tree[x].c[ql-1-l+1]-tree[x].c[l-1-l+1];//[l,ql-1]中有多少进入了左子树
        int tr=ql-1-l+1-tl;//[l,ql-1]中有多少进入了右子树
        if(sorted[mid]<=k)
            return cl+cquery(mid+1+tr,mid+1+tr+cr-1,k,mid+1,r,x*2+1);
        else return cquery(l+tl,l+tl+cl-1,k,l,mid,x*2);
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(~scanf("%d",&n))
        {
            for(int i=1;i<=n;i++)
                scanf("%d",&sorted[i]);
            init(1,n,1);//内存分配
            for(int i=1;i<=n;i++)
                tree[1].num[i]=sorted[i];
            sort(sorted+1,sorted+1+n);
            build(1,n,1);
            scanf("%d",&m);
            while(m--)
            {
                int a,b,c;
                scanf("%d %d %d",&a,&b,&c);
                printf("%d
    ",query(a+1,b+1,b-a+1-c+1,1,n,1));
            }
        }
        return 0;
    }
  • 相关阅读:
    背景图片自适应大小(平铺)
    墨卡托投影示意图
    C# 两个类的实例之间相同属性的值的复制
    C# 并行编程 Task
    C# 并行编程 PLINQ
    C# 并行编程 Parallel
    仰望星空
    Ubuntu的人道精神
    神经网络简介
    并行计算简介
  • 原文地址:https://www.cnblogs.com/mgz-/p/7444531.html
Copyright © 2011-2022 走看看