主席树

发布时间 2023-08-12 22:53:29作者: ChElsYqwq

详细介绍看心情可能会补

放这就是想方便参考顺便水篇博客

我们要维护一个数组的信息,但是我们也要查询历史信息

大概思想是不同线段树相同的部分共用点

每次修改都复制原来点再进行修改,这样肯定不冲突

通过记录不同版本根节点编号来做索引

其实写起来跟普通线段树的区别就是修改的时候需要重新建点并且要动态开点

主席树

定义 & 建树

int cnt, rt[MN], val[MN];
int ls[MN], rs[MN];

int build(int s,int e) {
	int p=++cnt;
	if(s<e) {
		int mid=(s+e)>>1;
		ls[p]=build(s,mid);
		rs[p]=build(mid+1,e);
	}
	return p;
}

修改

int modify(int pre,int s,int e,int x) {
	int p=++cnt; val[p]=val[pre];
	ls[p]=ls[pre], rs[p]=rs[pre];
	if(s==e) val[p]++;
	if(s<e) {
		int mid=(s+e)>>1;
		if(x<=mid) ls[p]=modify(ls[p],s,mid,x);
		else rs[p]=modify(rs[p],mid+1,e,x);
		val[p]=val[ls[p]]+val[rs[p]];
	}
	return p;
}

查询

int query(int p,int q,int s,int e,int l,int r) {
    if(l<=s&&e<=r) return val[q]-val[p];
    int mid=(s+e)>>1, ans=0;
    if(l<=mid) ans+=query(ls[p],ls[q],s,mid,l,r);
    if(r>mid) ans+=query(rs[p],rs[q],mid+1,e,l,r);
    return ans;
}