主席树Ⅰ
传说中的“高级”数据结构?
第一篇博客写一道模板题就行了。
主席树和普通的线段树写法上有什么区别?
-
左右孩子的表示方法
其实这和动态开点的线段树一个性质。我的写法就是把 \(change\) 函数改为 \(int\) 类型,实时返回孩子的编号。
-
公用信息
主席树的基本思想就是公用信息,能用之前的信息就用,达到节省时间和空间的目的。
所以需要做的就是在 change 函数里增加之前的节点 x ,先开一个新节点,把x里的信息全部复制到新节点里,看需要更新的在左儿子就更新左儿子编号,反之亦然。
-
记录根节点编号
很好理解。你总得知道某个前缀应该从哪里开始访问吧。
-
节点数量
为了保险,开区间大小的几十倍差不多。一般直接struct node{...}t[N<<5]
即可。
-
区间访问
不用把两个前缀的信息都求出来再相减,直接边递归边减即可。
#include<cstdio>
#include<algorithm>
//#define zczc
#define error printf("working\n");
using namespace std;
const int N=200010;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar(); }
wh*=f;return;
}
int m,n,q,a[N],b[N],c[N];
#define lc t[wh].left
#define rc t[wh].right
#define mid (t[wh].l+t[wh].r>>1)
int nodecnt=0;
struct node{
int l,r,left,right,data;
}t[N*50];
inline void pushup(int wh){
t[wh].data=t[lc].data+t[rc].data;
return;
}
int build(int l,int r){
int wh=++nodecnt;
t[wh].l=l,t[wh].r=r;
if(l==r)return wh;
lc=build(l,mid);
rc=build(mid+1,r);
return wh;
}
int change(int x,int pl){
int wh=++nodecnt;
t[wh].l=t[x].l,t[wh].r=t[x].r;
lc=t[x].left,rc=t[x].right;
t[wh].data=t[x].data;
if(t[wh].l==t[wh].r){
t[wh].data++;
return wh;
}
if(pl<=mid)lc=change(lc,pl);
else rc=change(rc,pl);
pushup(wh);
return wh;
}
int work(int lwh,int rwh,int want,int now){
if(t[lwh].l==t[lwh].r)return t[lwh].l;
int ldata=t[t[rwh].left].data-t[t[lwh].left].data;
if(ldata+now>=want)return work(t[lwh].left,t[rwh].left,want,now);
else return work(t[lwh].right,t[rwh].right,want,now+ldata);
}
#undef lc
#undef rc
#undef mid
int root[N];
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
read(m);read(q);
for(int i=1;i<=m;i++){
read(a[i]);
b[i]=a[i];
}
sort(b+1,b+m+1);
n=unique(b+1,b+m+1)-b-1;
for(int i=1;i<=m;i++){
a[i]=lower_bound(b+1,b+n+1,a[i])-b;
}
root[0]=build(1,n);
for(int i=1;i<=m;i++){
root[i]=change(root[i-1],a[i]);
}
int s1,s2,s3;
while(q--){
read(s1);read(s2);read(s3);
printf("%d\n",b[work(root[s1-1],root[s2],s3,0)]);
}
return 0;
}
一如既往,万事胜意