zoukankan      html  css  js  c++  java
  • POJ 2104 K-th Number

    题意:给出一个序列,若干查询,询问区间l到r的第k小值。

    解法:划分树可以最有效的解决这个问题……但是划分树只能解决这个问题= =主席树的应用范围比较广……所以只学了主席树……嗯……

    膜拜发明主席树的大神,引用一下他的话

    ..这个东西是当初我弱不会划分树的时候写出来替代的一个玩意..被一小撮别有用心的人取了很奇怪的名字<

    想法是对原序列的每一个前缀[1..i]建立出一颗线段树维护值域上每个数的出现次数,然后发现这样的树是可以减的,然后就没有然后了

    通过这位大神的博客学习了原理http://blog.csdn.net/metalseed/article/details/8045038

    通过这位大神的博客学习了代码http://www.cnblogs.com/Rlemon/archive/2013/05/23/3094635.html

    代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<math.h>
    #include<limits.h>
    #include<time.h>
    #include<stdlib.h>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define LL long long
    #define MAXN 100010
    
    using namespace std;
    
    struct node
    {
        int sum;
        int ls, rs;
        node() {sum = 0, ls = 0, rs = 0;}
    }T[MAXN * 20];
    int a[MAXN], b[MAXN], p[MAXN];//a是原数组,p代表a数组下标,b是离散化后数组
    int root[MAXN];//记录每个结点在T中的下标
    int sz;//当前数组使用长度
    void ins(int &i, int l, int r, int x)
    {
        T[++sz] = T[i];//复制上一节点作为新结点
        i = sz;//更新当前结点下标
        T[i].sum++;//更新线段树维护的和
        if(l == r)
            return ;
        int m = (l + r) >> 1;
        if(x <= m) ins(T[i].ls, l, m, x);//更改左儿子
        else ins(T[i].rs, m + 1, r, x);//更改右儿子
    }
    int query(int i, int j, int l, int r, int k)
    {
        if(l == r)
            return l;
        int t = T[T[j].ls].sum - T[T[i].ls].sum;//r线段树减去l-1的线段树值
        int m = (l + r) >> 1;
        if(t >= k) return query(T[i].ls, T[j].ls, l, m, k);
        else return query(T[i].rs, T[j].rs, m + 1, r, k - t);
    }
    bool cmp(int i, int j)
    {
        return a[i] < a[j];
    }
    int main()
    {
        int n, m;
        while(~scanf("%d%d", &n, &m))
        {
            for(int i = 1; i <= n; i++)
                scanf("%d", &a[i]), p[i] = i;
            sort(p + 1, p + n + 1, cmp);//按原数组大小对下标排序
            for(int i = 1; i <= n; i++)//离散化
                b[p[i]] = i;
            sz = 0;
            root[0] = 0;
            for(int i = 1; i <= n; i++)
            {
                root[i] = root[i - 1];
                ins(root[i], 1, n, b[i]);
            }
            while(m--)
            {
                int l, r, k;
                scanf("%d%d%d", &l, &r, &k);
                int t = query(root[l - 1], root[r], 1, n, k);
                printf("%d
    ", a[p[t]]);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    windows 服务中托管asp.net core
    asp.net core自定义端口
    asp.net core 2.1 部署IIS(win10/win7)
    Centos7 安装Tomcat并运行程序
    centos7 安装java运行环境
    linux(centos7) 常用命令和快捷键 持续验证更新中...
    CentOS7 设置yum源
    dotnet core 入门命令
    二项式系数学习笔记
    [容斥原理][莫比乌斯反演] Codeforces 803F Coprime Subsequences
  • 原文地址:https://www.cnblogs.com/Apro/p/4587133.html
Copyright © 2011-2022 走看看