• K-th Number POJ


     K-th Number POJ - 2104 

    You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment. 
    That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?" 
    For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5. 

    Input

    The first line of the input file contains n --- the size of the array, and m --- the number of questions to answer (1 <= n <= 100 000, 1 <= m <= 5 000). 
    The second line contains n different integer numbers not exceeding 109 by their absolute values --- the array for which the answers should be given. 
    The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k). 

    Output

    For each question output the answer to it --- the k-th number in sorted a[i...j] segment. 

    Sample Input

    7 3
    1 5 2 6 3 7 4
    2 5 3
    4 4 1
    1 7 3

    Sample Output

    5
    6
    3

    Hint

    This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.
     
     
    题意:求区间第k大
    题解:主席树的板子
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<sstream>
    #include<cmath>
    #include<stack>
    #include<cstdlib>
    #include <vector>
    #include<queue>
    using namespace std;
    
    #define ll long long
    #define llu unsigned long long
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    const int maxn =  1e5+5;
    const int  mod = 1e9+7;
    
    int n,q,m,tot;
    int a[maxn],t[maxn],T[maxn],lson[maxn*30],rson[maxn*30],c[maxn*30];
    
    void Init_hash()
    {
        for(int i=1;i<=n;i++)
            t[i] = a[i];
         sort(t+1,t+1+n);
         m = unique(t+1,t+1+n)-t-1;
    }
    
    int build(int l,int r)
    {
        int root = tot++;
        c[root] = 0;
        if (l != r)
        {
            int mid = (l+r) >> 1;
            lson[root] = build(l,mid);
            rson[root] = build(mid+1,r);
        }
        return root;
    }
    int Hash(int x)
    {
        return lower_bound(t+1,t+1+m,x)-t;
    }
    int update(int root,int pos,int val)
    {
        int newroot = tot ++,tmp = newroot;
        c[newroot] = c[root] + val;
        int l = 1,r = m;
        while(l <r)
        {
            int mid = (l+r)>>1;
            if(pos <= mid)
            {
                lson[newroot] = tot++;
                rson[newroot] = rson[root];
                newroot = lson[newroot];
                root = lson[root];
                r = mid;
            }
            else
            {
                rson[newroot] = tot ++;
                lson[newroot] = lson[root];
                newroot = rson[newroot];
                root = rson[root];
                l = mid + 1;
            }
            c[newroot] = c[root] + val;
        }
        return tmp;
    
    }
    int query(int left_root,int right_root,int k)
    {
        int l = 1,r = m;
        while(l < r)
        {
            int mid = (l+r) >> 1;
            if(c[lson[left_root]] - c[lson[right_root]] >= k)
            {
                r = mid;
                left_root = lson[left_root];
                right_root = lson[right_root];
            }
            else
            {
                l = mid + 1;
                k -= c[lson[left_root]] - c[lson[right_root]];
                left_root = rson[left_root];
                right_root = rson[right_root];
            }
        }
        return l;
    }
    int main()
    {
        scanf("%d%d",&n,&q);
        tot = 0;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        Init_hash();
        T[n+1] = build(1,m);
        for(int i=n;i;i--)
        {
            int pos = Hash(a[i]);
            T[i] = update(T[i+1],pos,1);
        }
        while(q--)
        {
            int l,r,k;
            scanf("%d%d%d",&l,&r,&k);
            printf("%d
    ",t[query(T[l],T[r+1],k)]);
        }
    }
    View Code
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<cstdlib>
    #include<queue>
    #include<set>
    #include<string.h>
    #include<vector>
    #include<deque>
    #include<map>
    using namespace std;
    #define INF 0x3f3f3f3f3f3f3f3f
    #define inf 0x3f3f3f3f
    #define eps 1e-4
    #define bug printf("*********
    ")
    #define debug(x) cout<<#x"=["<<x<<"]" <<endl
    typedef long long LL;
    typedef long long ll;
    const int maxn = 2e5 + 5;
    const int mod = 998244353;
    int n,m,a[maxn],root[maxn],cnt;
    vector<int>v;
    struct node{
        int l,r,sum;
    }T[maxn * 40];
    int getid(int x) {
        return lower_bound(v.begin(),v.end(),x) - v.begin() + 1;
    }
    void update(int l,int r,int &x,int y,int pos) {
        T[++cnt] = T[y],T[cnt].sum ++,x = cnt;
        if(l == r) return;
        int mid = (l + r) / 2;
        if(mid >= pos) update(l,mid,T[x].l,T[y].l,pos);
        else update(mid + 1,r,T[x].r,T[y].r,pos);
    }
    int query(int l,int r,int x,int y,int k) {
        if(l == r) return l;
        int mid = (l + r) / 2;
        int sum = T[T[y].l].sum - T[T[x].l].sum;
        if(sum >= k) return query(l,mid,T[x].l,T[y].l,k);
        else return query(mid + 1,r,T[x].r,T[y].r,k - sum);
    }
    void init() {
        cnt = 0;
        memset(root,0,sizeof root);
    }
    int main()
    {
        init();
        scanf("%d %d",&n,&m);
        for (int i = 1; i <= n; ++i) {
            scanf("%d",&a[i]);
            v.push_back(a[i]);
        }
        sort(v.begin(),v.end());
        v.erase(unique(v.begin(),v.end()),v.end());
        for (int i = 1; i <= n; ++i)
            update(1,n,root[i],root[i - 1],getid(a[i]));
        for (int i = 1; i <= m; ++i) {
            int x,y,k;
            scanf("%d %d %d",&x, &y, &k);
            printf("%d
    ",v[query(1,n,root[x - 1],root[y],k) - 1]);
        }
    }
    View Code
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<stack>
    #include<cstdlib>
    #include<queue>
    #include<set>
    #include<string.h>
    #include<vector>
    #include<deque>
    #include<map>
    using namespace std;
    #define INF 0x3f3f3f3f3f3f3f3f
    #define inf 0x3f3f3f3f
    #define eps 1e-4
    #define bug printf("*********
    ")
    #define debug(x) cout<<#x"=["<<x<<"]" <<endl
    typedef long long LL;
    typedef long long ll;
    const int maxn = 2e5 + 5;
    const int mod = 998244353;
    int n,m,a[maxn],root[maxn],cnt;
    /*
     root:代表每个历史版本线段树的根节点位置
     cnt:用作开辟新的树节点
     */
    vector<int>v;
    struct node{
        int l,r,sum;
    }T[maxn * 40];  //线段树区间统计,sum代表在这个区间数的个数
    int getid(int x) {      //获取离散数组后的下标
        return lower_bound(v.begin(),v.end(),x) - v.begin() + 1;
    }
    /*
     update函数:
     y代表前一棵树的节点位置,x是后面的节点位置
     */
    void update(int l,int r,int &x,int y,int pos) {
        //&x 引用节点指针扩展新节点
        T[++cnt] = T[y],T[cnt].sum ++,x = cnt;  //新开节点,将需要修改的树节点复制到新开辟节点,改变自己的sum
        if(l == r) return;
        int mid = (l + r) / 2;
        if(mid >= pos) update(l,mid,T[x].l,T[y].l,pos); //节点左边
        else update(mid + 1,r,T[x].r,T[y].r,pos);      //节点右边
    }
    int query(int l,int r,int x,int y,int k) {
        if(l == r) return l;
        int mid = (l + r) / 2;
        int sum = T[T[y].l].sum - T[T[x].l].sum;    //两颗线段树sum做差
        if(sum >= k) return query(l,mid,T[x].l,T[y].l,k);   //如果当前的结点个数sum比k要大的话,说明第k大的结点在左子树当中,就去遍历左子树
        else return query(mid + 1,r,T[x].r,T[y].r,k - sum); //如果当前的结点个数sum比k要小的话,说明第k大的结点在右子树当中,而左子树的结点个数是sum个,那就去找右子树中的第k-sum的数
    }
    void init() {
        cnt = 0;
        memset(root,0,sizeof root);
    }
    int main()
    {
        init();
        scanf("%d %d",&n,&m);
        for (int i = 1; i <= n; ++i) {
            scanf("%d",&a[i]);
            v.push_back(a[i]);      //离散化数组
        }
        sort(v.begin(),v.end());    //离散化数组
        v.erase(unique(v.begin(),v.end()),v.end()); //离散化数组
    
        for (int i = 1; i <= n; ++i) {
            update(1, n, root[i], root[i - 1], getid(a[i]));
        }
        for (int i = 1; i <= m; ++i) {
            int x,y,k;
            scanf("%d %d %d",&x, &y, &k);
            printf("%d
    ",v[query(1,n,root[x - 1],root[y],k) - 1]);
        }
    }
    View Code
  • 相关阅读:
    2D Polygons( Poygon) CGAL 4.13 -User Manual
    2D Convex Hulls and Extreme Points( Convex Hull Algorithms) CGAL 4.13 -User Manual
    Linear and Quadratic Programming Solver ( Arithmetic and Algebra) CGAL 4.13 -User Manual
    3D Spherical Geometry Kernel( Geometry Kernels) CGAL 4.13 -User Manual
    2D Circular Geometry Kernel ( Geometry Kernels) CGAL 4.13 -User Manual
    MySQL开启日志跟踪
    Cookie&Session
    Web服务器——WSGI
    win10上安装redis
    Ubantu上安装Redis
  • 原文地址:https://www.cnblogs.com/smallhester/p/10300566.html
Copyright © 2020-2023  润新知