• POJ 2104 K-th Number && 洛谷 P3834 【模板】可持久化线段树 1(主席树)


    我惊奇的发现这两道题一模一样

    题目背景

    这是个非常经典的主席树入门题——静态区间第K小

    数据已经过加强,请使用主席树。同时请注意常数优化

    题目描述

    如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值。

    输入输出格式

    输入格式:

     

    第一行包含两个正整数N、M,分别表示序列的长度和查询的个数。

    第二行包含N个整数,表示这个序列各项的数字。

    接下来M行每行包含三个整数l, r, kl,r,k , 表示查询区间[l, r][l,r]内的第k小值。

     

    输出格式:

     

    输出包含k行,每行1个整数,依次表示每一次查询的结果

     

    输入输出样例

    输入样例#1: 
    5 5
    25957 6405 15770 26287 26465 
    2 2 1
    3 4 1
    4 5 1
    1 2 2
    4 4 1
    输出样例#1: 
    6405
    15770
    26287
    25957
    26287
    

    说明

    数据范围:

    对于20%的数据满足:1 leq N, M leq 101N,M10

    对于50%的数据满足:1 leq N, M leq 10^31N,M103

    对于80%的数据满足:1 leq N, M leq 10^51N,M105

    对于100%的数据满足:1 leq N, M leq 2cdot 10^51N,M2105

    对于数列中的所有数a_iai,均满足-{10}^9 leq a_i leq {10}^9109ai109

    样例数据说明:

    N=5,数列长度为5,数列从第一项开始依次为[25957, 6405, 15770, 26287, 26465 ][25957,6405,15770,26287,26465]

    第一次查询为[2, 2][2,2]区间内的第一小值,即为6405

    第二次查询为[3, 4][3,4]区间内的第一小值,即为15770

    第三次查询为[4, 5][4,5]区间内的第一小值,即为26287

    第四次查询为[1, 2][1,2]区间内的第二小值,即为25957

    第五次查询为[4, 4][4,4]区间内的第一小值,即为26287

    解题思路:

    定义:主席树是一种可持久化的线段树 又叫函数式线段树

    刚开始学是不是觉得很蒙逼啊 其实我也是 

    主席树说简单了 就是保留你每一步操作完成之后的线段树 然后有可加减性

    呃 。。。 这么说好像还是有点生涩

    那么就拿poj2104来举例子吧 慢慢讲我觉得会很好的

    题意就是给你一个100000长度的数字 然后100000次询问[L,R]之间第k大的数字是多少

    这个很容易看出来 暴力根本不可以 黑你分分钟的事情啊 

    我们怎么办呢 想想线段树能不能做 想来想去 一颗线段树好像不能这么做 GG

    那么我们做一个美好的假设:

    我们建立100000棵美丽的线段树 每一个线段树的节点 表示这一个区间内有多少个数字

    第一棵线段树保存着把第一个数字插入进去之后 每个区间有多少个数字

    第二棵线段树保存着把第一个 第二个数字插入进去之后 每个区间有多少个数字

    第n棵线段树保存着把第1,2,3。。。。n个数字插入进去之后 每个区间有多少个数字

    好了 我们已经建立了这么多的线段树 我们接下来该怎么办呢?

    对 就是查询 

    可是如何查询呢? 假设我们要查询[l,r]内的第k大

    我们可以拿出第l-1 ,r 棵线段树,然后两者相减 我们想一下 这样不就得到了相当于插入了第l到r个点所建立的一棵线段树 这棵线段树每个节点保留的信息是:这个区间内数字的个数 然后我们往下二分查找 就可以得到第k大了

    现在的问题时 这么庞大的空间开销我们耗费不起 我们该如何建立这样的线段树呢?

    答案就是 我们要尽量利用重复节点 

    我们可以想一下 我们每次建立线段树 相对于前一棵线段树 我们只修改了它的一条路径 最多只有logn的变化 那么我们就存下这logn的变化 尽可能的利用重复节点 就可以达到重复使用的目的

    //原文:https://blog.csdn.net/qq_34271269/article/details/54849370

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #define maxn (int)(1e6+10)
     5 
     6 using namespace std;
     7 
     8 struct kkk {
     9     int cnt,l,r;
    10 }t[30*maxn];
    11 int init[maxn];
    12 int cop[maxn];
    13 int tc[maxn];
    14 int n,tcnt = 0,newn,m;
    15 
    16 void Discretization() {//离散化 
    17     sort(init,init+n);
    18     newn = unique(init,init+n) - init;
    19     for(int i = 0;i < n; i++) cop[i] = lower_bound(init,init+n,cop[i]) - init;
    20 }
    21 
    22 int add(int num,int bei,int l,int r) {
    23     ++tcnt;
    24     t[tcnt].cnt = t[bei].cnt + 1;
    25     int save = tcnt;
    26     int mid = (l + r) >> 1;
    27     if(l == r) {
    28         return save;
    29     }
    30     else if(num <= mid) {
    31         t[save].l = add(num,t[bei].l,l,mid);
    32         t[save].r = t[bei].r;
    33     }
    34     else {
    35         t[save].r = add(num,t[bei].r,mid + 1,r);
    36         t[save].l = t[bei].l;
    37     }
    38     return save;
    39 }
    40 
    41 int chaxun(int x,int y,int k,int l,int r) {
    42     if(l == r) return l;
    43     int p = t[t[y].l].cnt - t[t[x].l].cnt;
    44     int mid = (l + r) >> 1;
    45     if(k <= p) 
    46         return chaxun(t[x].l,t[y].l,k,l,mid);
    47     else 
    48         return chaxun(t[x].r,t[y].r,k-p,mid + 1,r);
    49 }
    50 
    51 int main()
    52 {
    53     scanf("%d%d",&n,&m);
    54     for(int i = 0;i < n; i++) {
    55         scanf("%d",&init[i]);
    56         cop[i] = init[i];
    57     }
    58     Discretization();
    59     for(int i = 1;i <= n; i++) {
    60         int p = add(cop[i-1],tc[i-1],0,n);
    61         tc[i] = p;
    62     }
    63     for(int i = 0;i < m; i++) {
    64         int x,y,k;
    65         scanf("%d%d%d",&x,&y,&k);
    66         int ans = chaxun(tc[x-1],tc[y],k,0,n);
    67         printf("%d
    ",init[ans]);
    68     }
    69     return 0;
    70 }
  • 相关阅读:
    oracle 排序字段自增长
    ORACLE REPLACE函数
    oracle非空不做更新
    Elasticsearch 5.4.3 聚合分组
    Elasticsearch 版本控制
    Elasticsearch 配置同义词
    Elasticseach的评分机制
    实现Ecshop商品跳到淘宝、京东等的购买链接
    修改ECSHOP系统红包序列号规律
    Ecshop后台订单列表增加”商品名”检索字段
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/10991241.html
Copyright © 2020-2023  润新知