【模板】区间第k小

我实在是太弱了现在才会这个东西QAQ。

主席树做法。

一张关于主席树的无字说明

线段树\(2\)是只单点修改了实心酒红色点的线段树\(2\),线段树\(2\)中的蓝色节点实际上就是线段树\(1\)的蓝色节点,我们只是把地址复制过来了。

我们多开了一个线段树,但是节点数量却只多了\(log\)层,那么对于\(n\)的历史版本保留就提供了\(O(nlogn)\)的数据结构啦。

具体代码怎么实现?我研究了一下,发现实际写出来的代码和大家常写的代码是一样的。实现其实非常简单,只需要在普通线段树上稍微修改一下。

如何访问历史版本?我们可以开一个\(rt(i)\)数组表示\(i\)号版本的根节点的编号,对于线段树每个节点我们要记录\(seg_L,seg_R,data\),递归时只要访问\(seg_{L/R}\)的值就好了,不需要很大的修改。

其实我还想问一个问题,就是我发现这种主席树支持单点修改,区间查询,但是我想问如果是区间修改,而且是\(n\times n\)的修改怎么办?因为我发现修改一个点就一定会产生新的\(n\)个节点了。

实际上主席树就是让整个线段树有了两维下标,所以对于什么二维数点啊什么什么之类的也有用。

这个问题以后再解决,那么有了主席树工具之后怎么解此题?

不是两维下标吗?建立一个下标是值域和位置的线段树(按照给的序列的顺序建立主席树,主席树存储的东西是值域内有多少个数),然后区间的限制可以直接是\(rt_R-rt_{L-1}\)很方便地查询。

实际上,主席树教会我们如何弄一个可持久化数组!有了可持久化数组,什么可持久化数据结构不行!平衡树呢:)

#include<bits/stdc++.h>

using namespace std;typedef long long ll;
#define RP(t,a,b) for(register int t=(a),edd=(b);t<=edd;++t)
#define midd register int mid=(l+r)>>1
#define TMP template < class ccf >
#define lef l,mid,seg[pos].l
#define rgt mid+1,r,seg[pos].r
TMP inline ccf qr(ccf b){
register char c=getchar();register int q=1;register ccf x=0;
while(c<48||c>57)q=c==45?-1:q,c=getchar();
while(c>=48&&c<=57)x=x*10+c-48,c=getchar();
return q==-1?-x:x;}
TMP inline ccf Max(ccf a,ccf b){return a<b?b:a;}
TMP inline ccf Min(ccf a,ccf b){return a<b?a:b;}
TMP inline ccf Max(ccf a,ccf b,ccf c){return Max(a,Max(b,c));}
TMP inline ccf Min(ccf a,ccf b,ccf c){return Min(a,Min(b,c));}
TMP inline void READ(ccf* _arr,ccf* _b,int _n){RP(t,1,_n) _b[t]=_arr[t]=qr((ccf)1);}
//----------------------template&IO---------------------------
#define pushup(pos) (seg[pos].data=seg[seg[pos].l].data+seg[seg[pos].r].data)
const int maxn=2e5+5;
struct SEG{int l,r,data;}seg[maxn*81];//log2e5=17 , 17*4=75 int rt[maxn];int data[maxn],sav[maxn];int sz,cnt;
int n,m; void build0(int l,int r,int pos){
if(l==r)return;midd;
seg[pos].l=++cnt;seg[pos].r=++cnt;
build0(lef);build0(rgt);
} void build(int last,int k,int l,int r,int pos){
if(l==r) { seg[pos].data=seg[last].data+1; return; }midd;
if(k<=mid){seg[pos].l=++cnt;seg[pos].r=seg[last].r;build(seg[last].l,k,lef);}
else {seg[pos].l=seg[last].l;seg[pos].r=++cnt;build(seg[last].r,k,rgt);}
pushup(pos);
} int a(int L,int R,int l,int r,int k){
if(l>=r) return l;
register int t=seg[seg[R].l].data-seg[seg[L].l].data;midd;
if(t>=k) return a(seg[L].l,seg[R].l,l,mid,k);
else return a(seg[L].r,seg[R].r,mid+1,r,k-t);
} int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
n=qr(1);m=qr(1);
READ(data,sav,n);
sort(sav+1,sav+n+1);
sz=unique(sav+1,sav+n+1)-sav-1;
RP(t,1,n) data[t]=lower_bound(sav+1,sav+sz+1,data[t])-sav;
cnt=rt[0]=1;build0(1,sz,1);
RP(t,1,n){rt[t]=++cnt;build(rt[t-1],data[t],1,sz,rt[t]);}
RP(t,1,m){
register int t1,t2,t3;
t1=qr(1);t2=qr(1);t3=qr(1);
printf("%d\n",sav[a(rt[t1-1],rt[t2],1,sz,t3)]);
}
return 0;
}

还有一道模板题,也放进来吧

#include<bits/stdc++.h>

using namespace std;typedef long long ll;
#define DRP(t,a,b) for(register int t=(a),edd=(b);t>=edd;--t)
#define RP(t,a,b) for(register int t=(a),edd=(b);t<=edd;++t)
#define ERP(t,a) for(register int t=head[a];t;t=e[t].nx)
#define midd register int mid=(l+r)>>1
#define TMP template < class ccf >
#define lef l,mid,sL[pos]
#define rgt mid+1,r,sR[pos]
const int maxn=1e6+5;
char buf[maxn], *p1, *p2;
inline char gc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, maxn, stdin), p1 == p2) ? EOF : *p1++; }
TMP inline ccf qr(ccf b){
register char c=gc();register int q=1;register ccf x=0;
while(c<48||c>57)q=c==45?-1:q,c=gc();
while(c>=48&&c<=57)x=x*10+c-48,c=gc();
return q==-1?-x:x;}
TMP inline ccf Max(ccf a,ccf b){return a<b?b:a;}
TMP inline ccf Min(ccf a,ccf b){return a<b?a:b;}
TMP inline ccf Max(ccf a,ccf b,ccf c){return Max(a,Max(b,c));}
TMP inline ccf Min(ccf a,ccf b,ccf c){return Min(a,Min(b,c));}
TMP inline ccf READ(ccf* _arr,int _n){RP(t,1,_n)_arr[t]=qr((ccf)1);}
//----------------------template&IO---------------------------
int seg[maxn*81];
int data[maxn*81];
int sL[maxn*81];
int sR[maxn*81];
int rt[maxn];
int cnt;
int n,m;
void build0(int l,int r,int pos){
if(l==r) {data[pos]=qr(1);return;}
sL[pos]=++cnt;sR[pos]=++cnt;midd;
build0(lef);build0(rgt);
} void build(int last,int k,int l,int r,int pos){
if(l==r) {data[pos]=qr(1);return;}midd;
if(k<=mid){sL[pos]=++cnt;sR[pos]=sR[last];build(sL[last],k,lef);}
else {sR[pos]=++cnt;sL[pos]=sL[last];build(sR[last],k,rgt);}
} void upd(int last,int k,int l,int r,int pos){
if(l==r) {printf("%d\n",data[pos]=data[last]);return;}midd;
if(k<=mid){sL[pos]=++cnt;sR[pos]=sR[last];upd(sL[last],k,lef);}
else {sR[pos]=++cnt;sL[pos]=sL[last];upd(sR[last],k,rgt);}
} int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
n=qr(1);m=qr(1);
rt[0]=cnt=1;
build0(1,n,1);
for(register int t=1,t1,t2;t<=m;++t){
t1=qr(1);t2=qr(1);rt[t]=++cnt;
if(t2==1) build(rt[t1],qr(1),1,n,rt[t]);
else upd(rt[t1],qr(1),1,n,rt[t]);
}
return 0;
}

【模板】区间第k小的更多相关文章

  1. HDU 2665.Kth number-可持久化线段树(无修改区间第K小)模板 (POJ 2104.K-th Number 、洛谷 P3834 【模板】可持久化线段树 1(主席树)只是输入格式不一样,其他几乎都一样的)

    Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  2. 区间第K小——可持久化线段树模板

    概念 可持久化线段树又叫主席树,之所以叫主席树是因为这东西是fotile主席创建出来的. 可持久化数据结构思想,就是保留整个操作的历史,即,对一个线段树进行操作之后,保留访问操作前的线段树的能力. 最 ...

  3. 「BZOJ3065」带插入区间第K小值 替罪羊树×线段树

    题目描述 从前有\(n\)只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力\(a_i\).跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间\(k\)小值.他 ...

  4. 主席树--动态区间第k小

    主席树--动态区间第\(k\)小 模板题在这里洛谷2617. 先对几个问题做一个总结: 阅读本文需要有主席树的基础,也就是通过区间kth的模板题. 静态整体kth: sort一下找第k小,时间复杂度\ ...

  5. POJ2104 区间第k小

    题意就是区间第k大…… 题解: 前段时间用主席树搞掉了…… 如今看到划分树,是在想来写一遍,结果18号对着学长的代码调了一上午连样例都没过,好桑心…… 今天在做NOI2010超级钢琴,忽然发现用划分树 ...

  6. 主席树总结(经典区间第k小问题)(主席树,线段树)

    接着上一篇总结--可持久化线段树来整理吧.点击进入 这两种数据结构确实有异曲同工之妙.结构是很相似的,但维护的主要内容并不相同,主席树的离散化.前缀和等思想也要更难理解一些. 闲话 话说刚学习主席树的 ...

  7. ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解

    题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...

  8. 【XSY2720】区间第k小 整体二分 可持久化线段树

    题目描述 给你你个序列,每次求区间第\(k\)小的数. 本题中,如果一个数在询问区间中出现了超过\(w\)次,那么就把这个数视为\(n\). 强制在线. \(n\leq 100000,a_i<n ...

  9. A - 低阶入门膜法 - K-th Number (主席树查询区间第k小)

    题目链接:https://cn.vjudge.net/contest/284294#problem/A 题目大意:主席树查询区间第k小. 具体思路:主席树入门. AC代码: #include<i ...

随机推荐

  1. Apollo 分布式配置中心

    1.  介绍 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用于微服务配置 ...

  2. java值传递和引用传递的理解

    java的基础数据类型有:(byte.short.int.long.float.double.char.boolean)八种 基础数据都是值传递,其他都是引用传递.但是引用传递要特别注意:String ...

  3. Java中的JAR/EAR/WAR包的文件夹结构说明(转)

    JAR包:打成JAR包的代码,一般作为工具类,在项目中,会应用到N多JAR工具包. WAR包:JAVA WEB工程,都是打成WAR包,进行发布,如果我们的服务器选择TOMCAT等轻量级服务器,一般就打 ...

  4. main函数参数

    方法1. C/C++语言中的main函数,经常带有参数argc,argv,如下: int main(int argc, char** argv) int main(int argc, char* ar ...

  5. 使用LeakCanary遇到的问题 就是不弹出来

    今天楼主遇到引用LeakCanary时代码跟官网一样但是就不弹出来.楼主新建项目就可以正常使用.楼主郁闷半天,现在终于整出来了. 楼主主工程app引用module为thirdParty,本想为了整洁三 ...

  6. yii2操作数据库 mysql 读写分离 主从复制

    转载地址:http://www.kuitao8.com/20150115/3471.shtml 开始使用数据库首先需要配置数据库连接组件,通过添加 db 组件到应用配置实现("基础的&quo ...

  7. 2017.2.12 开涛shiro教程-第七章-与Web集成

    2017.2.9 开涛shiro教程-第七章-与Web集成(一) 原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. ...

  8. 转: maven打可执行的jar包以及classpath设置

    from:  http://drizzlewalk.blog.51cto.com/2203401/416508

  9. mongoDb学习以及spring管理 (包括百度云配置)

    1.windows下的安装http://www.cnblogs.com/liuzhiying/p/5915741.html 2.慕课网学习单机操作mongoDb 赋权限:http://blog.csd ...

  10. Android开发第一讲之目录结构和程序的执行流程

    1.如何在eclipse当中,修改字体 下面的这种办法,可以更改xml的字体 窗口--首选项--常规--外观--颜色和字体--基本--文本字体--编辑Window --> Preferences ...