题意 : 给出一个含有 N 个数的序列,然后有 M 次问询,每次问询包含 ( L, R, K ) 要求你给出 L 到 R 这个区间的第 K 大是几

分析 :

求取区间 K 大值是个经典的问题,可以使用的方法有很多,我听过的只有主席树、整体二分法、划分树、分块……

因为是看《挑战》书介绍的平方分割方法(分块),所以先把分块说了,其他的坑以后再填

分块算法思想是将区间分为若干块,一般分为 n1/2 块然后在每块维护所需信息,可以把复杂度降到 O(根号n)

具体的分析和代码在《挑战程序设计竞赛》有很详细的解释,这里说一下代码的实现细节

题目在实现的时候用的是这种 [L, R) 左闭右开区间,这样的区间表示法在 STL 和 JAVA的类库中很常用

这样有很多优点,其中一个优点就是区间的长度是L ~ R,而判断两个区间的交或者并的时候思考的难度也降低很多。

L < R代表区间有值,L == R代表区间到了最后。用闭区间就特别麻烦,下面我给出的代码就是用闭区间的,纠结了我好久...

#include<vector>
#include<stdio.h>
#include<algorithm>
using namespace std;
;
;
vector<int> bucket[maxn / B];
int num[maxn], arr[maxn];
int N, M;

int main(void)
{

    while(~scanf("%d %d", &N, &M)){
        ; i<N; i++){
            scanf("%d", &arr[i]);
            bucket[i / B].push_back(arr[i]);
            num[i] = arr[i];
        }

        sort(num, num + N);
        ; i<N/B; i++)
            sort(bucket[i].begin(), bucket[i].end());

        int L, R, K;
        while(M--){
            scanf("%d %d %d", &L, &R, &K);
            L--, R--;
            , ub = N - , ans = -;
            while(ub >= lb){
                );
                ;
                int TL = L, TR = R;
                 > TL && TL % B != ) if(arr[TL++] <= num[mid]) c++;
                 > TL && (TR+) % B != ) if(arr[TR--] <= num[mid]) c++;

                while(TR >= TL){
                    c += upper_bound(bucket[TL/B].begin(), bucket[TL/B].end(), num[mid]) - bucket[TL/B].begin();
                    TL += B;
                }

                ;
                ;
            }
            printf("%d\n", num[ans]);
        }
    }
    ;
}

2018-05-07 更新

省赛被 可持久化Trie 打爆,决定学习一下可持久化数据结构

学了主席树,离线求取 K 大值,注意一下离散化

#include<stdio.h>
#include<algorithm>
using namespace std;
;
];
int root[maxn], sz;
void Insert(int pre, int cur, int p, int l, int r)
{
    if(l == r){
        Node[cur].v = Node[pre].v + ;
        return ;
    }

    );
    if(p <= m){
        Node[cur].lc = ++sz;
        Node[cur].rc = Node[pre].rc;
        Insert(Node[pre].lc, Node[cur].lc, p, l, m);
    }else{
        Node[cur].rc = ++sz;
        Node[cur].lc = Node[pre].lc;
        Insert(Node[pre].rc, Node[cur].rc, p, m+, r);
    }

    Node[cur].v = Node[Node[cur].lc].v + Node[Node[cur].rc].v;
}

int query(int L, int R, int l, int r, int k)
{
    if(l == r) return l;
    );
    int tmp = Node[Node[R].lc].v - Node[Node[L].lc].v;
    if(tmp >= k)
        return query(Node[L].lc, Node[R].lc, l, m, k);
    else
        , r, k-tmp);
}

int arr[maxn];
int mp[maxn];
int main(void)
{
    int N, M;
    scanf("%d %d", &N, &M);
    ; i<N; i++)
        scanf("%d", &arr[i]),
        mp[i] = arr[i];

    sort(mp, mp+N);
    int len = unique(mp, mp+N) - mp;

    ; i<=N; i++){
        ]) - mp;
        root[i] = ++sz;
        Insert(root[i-], root[i], x+, , len);
    }

    int i, j, k;
    while(M--){
        scanf("%d %d %d", &i, &j, &k);
        ], root[j], , len, k);
        printf(]);
    }
    ;
}

POJ 2104 K-th Number ( 求取区间 K 大值 || 主席树 || 离线线段树)的更多相关文章

  1. [luoguP1440] 求m区间内的最小值(单调队列 || 线段树)

    传送门 这种水题没必要搞线段树了,单调队列就行啊. ——代码 #include <cstdio> ; , t = ; int a[MAXN], q[MAXN]; int main() { ...

  2. 线性时间求取第 K 大数

    求 Top K 的算法主要有基于快速排序的和基于堆的这两种,它们的时间复杂度都为 \(O(nlogK)\).借助于分治思想,以及快速排序的区间划分,我们可以做到 \(O(n)\) 时间复杂度.具体算法 ...

  3. poj 1523Tarjan算法的含义——求取割点可以分出的连通分量的个数

    poj 1523Tarjan算法的含义——求取割点可以分出的连通分量的个数 题目大意:如题目所示 给你一些关系图——连通图,想要问你有没有个节点,损坏后,可以生成几个互相独立的网络(也就是连通分量), ...

  4. hdu6003 Problem Buyer 贪心 给定n个区间,以及m个数,求从n个区间中任意选k个区间,满足m个数都能在k个区间中找到一个包含它的区间,如果一个区间包含了x,那么 该区间不能再去包含另一个数,即k>=m。求最小的k。如果不存在这样的k,输出“IMPOSSIBLE!”。

    /** 题目:hdu6003 Problem Buyer 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6003 题意:给定n个区间,以及m个数,求从n个区 ...

  5. 求余区间的求和类问题 离线+线段树 HDU4228

    题目大意:给一个数组a,他的顺序是严格的单调增,然后有如下三个操作 ①加入一个val到a数组里面去,加入的位置就是a[i-1]<val<a[i+1] ②删除一个a[i]=val的值 ③查询 ...

  6. Splay(区间翻转)&树套树(Splay+线段树,90分)

    study from: https://tiger0132.blog.luogu.org/slay-notes P3369 [模板]普通平衡树 #include <cstdio> #inc ...

  7. HDU 5700 区间交 离线线段树

    区间交 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5700 Description 小A有一个含有n个非负整数的数列与m个区间.每个区间可以表示为 ...

  8. [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)

    [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...

  9. bzoj 3110 [Zjoi2013]K大数查询——线段树套线段树(标记永久化)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3110 第一道线段树套线段树! 第一道标记永久化! 为什么为什么写了两个半小时啊…… 本想线段 ...

随机推荐

  1. 批处理文件将多台连接的手机安装同一个APP

    :adb devices > C:\Users\aaminaxu\Desktop\a.txt :1.首先获取连接到电脑的手机的设备信息将其保存到C盘的a.txt文件中::2.将保存的txt文件中 ...

  2. 【HANA系列】SAP HANA数据处理的理解与分析一

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA数据处理的理解与 ...

  3. 应用安全 - 工具 - 浏览器 - IE浏览器 - 漏洞汇总

    CVE-2014-6332 Date 2014.11 CVE-2016-0189 | MS16-051 Date 2016年初 CVE-2018-8174

  4. Java中的静态变量、静态方法、静态代码块

    转载自http://www.cnblogs.com/panjun-Donet/archive/2010/08/10/1796209.html (一)静态方法(1)在Java里,可以定义一个不需要创建对 ...

  5. 一、Zabbix-学习列表

    近期本人在求职,面试了几家,觉得监控是一个很重要的事情,所以决定深入学习一下监控.目前的监控系统有很多,Zabbix是目前应用最广泛的开源监控之一,功能比较完善,所以决定学习一下. 目前将学习zabb ...

  6. 红帽学习笔记[RHCSA] 第六课[进程、服务相关]

    第六课 进程 进程:已经启动的可执行程序的运行中的实例.每个进程都有自己的地址空间,并占用了一定的系统资源. 如何产生一个进程 执行程序或命令 计划任务 在终端中对进程管理 运行一个前台进程 [roo ...

  7. angulart 常用

    angular: 使用 echarts npm install echarts --save // 安装declare const echarts: any; // 引入https://www.ech ...

  8. 第九周总结&第七次实验报告

    实验7 实验任务详情: 完成火车站售票程序的模拟. 要求: (1)总票数1000张: (2)10个窗口同时开始卖票: (3)卖票过程延时1秒钟: (4)不能出现一票多卖或卖出负数号票的情况. 实验过程 ...

  9. .Net Core - 使用Supervisor进行托管部署

    环境 CentOS 7 x64,详见 安装CentOS7虚拟机 .Net Core 2.1.801 详见 CentOS 7 下安装.NET Core SDK 2.1 ftp  详见  CentOS7 ...

  10. vue-sticky组件详解

    sticky简介 sticky的本意是粘的,粘性的,使用其进行的布局被称为粘性布局. sticky是position属性新推出的值,属于CSS3的新特性,常用与实现吸附效果. 设置了sticky布局的 ...