前言
呃,首先声明,看这篇博客前,最好先去学一学主席树,毕竟可持久化数组的实现是完全基于主席树的(那些乱七八糟的玄学算法请走开)。
L i n k Link Link
主席树详见博客可持久化专题(一)——浅谈主席树:可持久化线段树
顺便吐槽一句,可持久化数组这个名字听起来真的很智障。
简介
可持久化数组支持单点修改和单点查询。
.单点修改和单点查询这种东西不是直接数组就能解决了吗?干嘛要可持久化?
因为要用到历史版本啊!
基本思路
思路1:我们可以考虑对每一个版本开一个数组,这就是最暴力的打法了,这样显然会MLE+TLE。
思路2:高级一点,我们可以考虑对每一个版本建一棵线段树,查询时在线段树上查询,这样的效率还不如一个暴力数组,结果会MLE+TLE得更惨。
思路3:虽然思路2会炸飞,但是,它显然比思路1更容易优化。看到一群线段树,我们很容易想到用可持久化线段树——主席树来优化它。
具体实现
在这里,主席树的作用就不是查询区间第 k k k大了,而是在每一个叶子节点上记录当前版本这一位上的值。
如果你主席树打得够熟练,这就是一道水题了,直接上代码吧:(还是洛谷上的一道板子题)
#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define LL long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++)
#define pc(ch) (pp_<100000?pp[pp_++]=(ch):(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=(ch)))
#define N 1000000
int pp_=0;char ff[100000],*A=ff,*B=ff,pp[100000];
using namespace std;
int n,Q,tot=0,rt[N+5],a