YEAH!我也是一个AC主席树模板的人了!

其实是个半吊子

我将尽量详细的讲出我的想法。

主席树太难,我们先搞普通线段树好了

普通线段树怎么做?我的想法是查询K次最小值,每次查完把查的数改成INF,查完再改回来。。。

MDZZ

于是就有了主席树。

先不考虑主席树,我们来考虑一个奇特的线段树。

一般的线段树,数列位置是下标,而把数列维护值作为线段树中存的元素。

那我们如果反过来,把数列元素当做线段树的下标。。。???

比如说数列【4 2 3 1】

如果线段树的下标是1、2、3、4.。。。。。?

那  在数据离散之后

我们要查第K大的数是不是比较简单。。。

NIUBI!

主席树同理。主席树的每一个节点都是一颗线段树,也就是说对【1~n】的每个前缀建一棵线段树,线段树的每一个节点存前缀【1~i】中属于【L~R】的数有多少个。比如根节点是[1..n],一共i个数,sum[root] = i;根节点的左儿子是[1..(L+R)/2],若不大于(L+R)/2的数有x个,那么sum[root.left] = x)。若要查找[i..j]中第k大数时,设某结点x,那么x.sum[j] - x.sum[i - 1]就是[i..j]中在结点x内的数字总数。而对每一个前缀都建一棵树,会MLE,观察到每个[1..i]和[1..i-1]只有一条路是不一样的,那么其他的结点只要用回前一棵树的结点即可,时空复杂度为O(nlogn)。

那主席树怎么做这道题呢?

最一开始建一棵空的线段树,也就是最开始的主席树。设这第0棵线段树的根节点为rt[0],

然后一个个把原序列元素加到对应位置。

比如我们刚举的那个例子,图片如下

就像这样。观察到节点4、5、6、7对应原序列值域1~4。原序列前缀【1~0】中每个节点的值都是0.

更新时可以发现只有一条路上的节点值有改变,于是新的线段树只需要自己新建logn个节点,其他的可以从旧线段树搬来:

可以看到新的线段树使用了一部分旧线段树的节点,因为这些节点没有任何改动,新建太浪费空间时间。

这样我们得到区间[l, r]的数要查询第k大便很容易了,设左节点中存的个数为cnt,当k<=cnt时,我们直接查询左儿子中第k小的数即可,如果k>cnt,我们只要去查右儿子中第k-cnt小的数即可,这边是一道很简单的线段树了。就如查找[1, 3]的第2小数,从根节点1向下搜,发现左儿子2的个数为1,1<2,所有去右儿子3中搜第2-1级第1小的数,然后再往下搜,发现左儿子6便可以了,此时已经搜到底端,所以直接返回节点6维护的值3即可就可以了。

附上代码

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define mid ((l+r)>>1)
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} long long *que;
long long *f;
long long *rt;
long long *ls;
long long *rs;
long long *sum;
long long tot;
long long *d;
void build(long long int &o,int l,int r){
o=++tot;
sum[o]=;
if(l==r) return;
build(ls[o],l,mid);
build(rs[o],mid+,r);
} void update(long long &o,int l,int r,int last,long long p){
o=++tot;
ls[o]=ls[last];
rs[o]=rs[last];
sum[o]=sum[last]+;
if(l==r) return;
if(p<=mid) update(ls[o],l,mid,ls[last],p);
else update(rs[o],mid+,r,rs[last],p);
} long long query(int from,int to,int l,int r,long long k){
if(l==r) return l;
long long cnt=sum[ls[to]]-sum[ls[from]];
if(k<=cnt) return query(ls[from],ls[to],l,mid,k);
else return query(rs[from],rs[to],mid+,r,k-cnt);
} struct Que{
int ID,tme;
bool operator <(const Que &a)const{
return tme<a.tme;
}
}e[];
int Ans[][]; int cc=;
int ss;
int main(){
int m=read(),n=read();
que=new long long[m+];
f=new long long[m+];
rt=new long long [m*];
ls=new long long [m*];
rs=new long long [m*];
sum=new long long [m*];
d=new long long [m*];
for(int i=;i<=m;++i){
que[i]=read();
f[i]=d[i]=que[i];
}
sort(f+,f+n+);
int size=unique(f+,f+n+)-(f+);
build(rt[],,size);
for(int i=;i<=m;++i) que[i]=lower_bound(f+,f+size+,que[i])-f;
for(int i=;i<=n;++i) e[i]=(Que){i,read()};
sort(e+,e+n+);
for(int i=;i<=n;++i){
int tme=e[i].tme,ID=e[i].ID;
while(cc<=tme){
update(rt[cc],,size,rt[cc-],que[cc]);
cc++;
}
int ans=query(rt[],rt[tme],,size,++ss);
Ans[ID][]=f[ans];
Ans[ID][]=;
}
for(int i=;i<=n;++i)
if(Ans[i][])
printf("%d\n",Ans[i][]);
return ;
}

【Luogu】P3384主席树模板(主席树查询K小数)的更多相关文章

  1. Luogu P3384 【【模板】树链剖分】

    转载请注明出处,部分内容引自banananana大神的博客 ~~别说你不知道什么是树~~╮(─▽─)╭(帮你百度一下) 先来回顾两个问题:1,将树从x到y结点最短路径上所有节点的值都加上z 这也是个模 ...

  2. 洛谷3834 hdu2665主席树模板,动态查询区间第k小

    题目链接:https://www.luogu.com.cn/problem/P3834 对于区间查询第k小的问题,在区间数量达到5e5的时候是难以用朴素数据结构实现的,这时候主席树就应运而生了,主席树 ...

  3. 主席树-指针实现-找第k小数

    主席树,其实就是N颗线段树 只是他们公用了一部分节点(๑•̀ㅂ•́)و✧ 我大部分的代码是从一位大佬的那里看到的 我这个垃圾程序连Poj2104上的数据都过不了TLE so希望神犇能给我看看, 顺便给 ...

  4. 洛谷3372线段树模板题 对区间+k或者查询区间和

    #include<bits/stdc++.h> using namespace std; typedef unsigned int ui; typedef long long ll; ty ...

  5. [Luogu 3701] 「伪模板」主席树

    [Luogu 3701] 「伪模板」主席树 这是一道网络流,不是主席树,不是什么数据结构,而是网络流. 题目背景及描述都非常的暴力,以至于 Capella 在做此题的过程中不禁感到生命流逝. S 向 ...

  6. [luogu P3384] [模板]树链剖分

    [luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...

  7. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  8. 洛谷P3834 [模板]可持久化线段树1(主席树) [主席树]

    题目传送门 可持久化线段树1(主席树) 题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定 ...

  9. 主席树的各类模板(区间第k大数【动,静】,区间不同数的个数,区间<=k的个数)

    取板粗   好东西来的 1.(HDOJ2665)http://acm.hdu.edu.cn/showproblem.php?pid=2665 (POJ2104)http://poj.org/probl ...

随机推荐

  1. arcgis jsapi接口入门系列(2):图层基础操作

    //图层相关demo layerFun: function () { //获取地图的所有图层(不包括的图层类型:底图图层(basemaps)) let layers = this.map.layers ...

  2. OPENFIRE 启动流程

    在java>org>jivesoftware>openfire>starter,该类中的main方法启动,有图为证: 在start中方法分别调用unpackArchives和f ...

  3. navicate连接mysql

    1. 打开navicate,选择连接 2. 编辑连接属性 编辑完成之后,连接成功.

  4. 几个不错的APP网站。

    http://www.yunshipei.com/yunshipei.html http://www.appcan.cn/

  5. 并查集+思维——X-Plosives

    一.问题描述(题目链接) 有n种化合物,每种化合物由两种元素组成.当几种的化合物数量等于他们所含不同元素的数量时,就会发生爆炸.现在依次给出化合物的组成,当新的化合物与之前的化合物放在一起会发生爆炸时 ...

  6. 改变console.log的输出样式

    console.log允许你通过css来格式化输出,格式如下: console.log(‘%c字符串%c字符串’, 样式1, [样式2]) 其中”%c”为模板字符串 例子: 1 console.log ...

  7. 公共Service的抽取小例

    package cn.sxx.service; import java.util.List; public interface BaseService<T,Q> { public void ...

  8. 以太坊开发框架Truffle学习笔记

    from http://truffleframework.com/docs/getting_started/project 1. 安装node.js 8.11.2 LTS 2. 安装Truffle $ ...

  9. 电商技术中企业数据总线ESB和注册服务管理的区别

    一.概述 1.什么是ESB 就是企业数据总线的意思,他的核心功能就是兼容各种协议接口,可以将数据在各种协议之间进行流转,并且可以针对数据格式进行编排转换. 异构系统,功能繁多,复杂 代表性的项目有:J ...

  10. java在线聊天项目0.1版本 制作客户端窗体,使用swing(用户界面开发工具包)和awt(抽象窗口工具包)

    建立Chat项目,并在项目中创建窗口类 package com.swift; import java.awt.BorderLayout; import javax.swing.JFrame; impo ...