首页 > 其他分享 >树上可持久化线段树

树上可持久化线段树

时间:2023-08-26 16:26:13浏览次数:39  
标签:持久 shu 线段 tr 节点 return 树上 ll gs

例题传送门:Count on a tree

简要题意:有棵\(n\)个节点的树,每次点有个权值\(a_i\),每次询问给出\(u,v,k\),求\(u,v\)两个节点的简单路径上(包括\(u,v\))上第\(k\)小的点,保证数据有解,强制在线

\(1\le n,m\le 10^5,a_i\in[1,2^{31}-1]\)

首先,第\(k\)小就可以想到要可持久化线段树,动态开点。

但是我们发现,要尽量快的寻找\(u,v\)的简单路径上包含的节点。

然后我们就可以用一个很经典的\(trick\): 设\(s_i\)为\(i\)到根节点的路径上包含的节点,则 \(u,v\)的简单路径上包含的节点为:

\[s_u+s_v-s_{LCA(u,v)}-s_{fa[LCA(u,v)]} \]

考虑可持久化线段树存每个\(i\)到根节点的简单路径上包含的节点,只有注意\(a_i\)的离散化就可以做出这道题了

上代码:

#include<bits/stdc++.h>
#define ll int
using namespace std;
const ll N=1e5+50;
ll n,m,u,v,k,ans;
vector<ll> e[N];
struct jgt
{
	ll x,pos;
}a[N];
ll re[N];
bool cmp1(jgt t1,jgt t2)
{
	return t1.x<t2.x;
}
bool cmp2(jgt t1,jgt t2)
{
	return t1.pos<t2.pos;
}
struct jgt1
{
	ll l,r,gs;
}tr[N*25];
ll rt[N],tot;
ll f[N][25],dep[N];
void add(ll &now,ll last,ll l,ll r,ll md)
{
	now=++tot;
	tr[now]=tr[last];
	tr[now].gs++;
	if(l==r) return ;
	ll mid=(l+r)/2;
	if(md<=mid) add(tr[now].l,tr[last].l,l,mid,md);
	else add(tr[now].r,tr[last].r,mid+1,r,md);
}
void dfs(ll wz,ll last)
{
	add(rt[wz],rt[last],1,n,a[wz].x);
	f[wz][0]=last;
	dep[wz]=dep[last]+1;
	for(ll i=1;i<=18;i++)
	f[wz][i]=f[f[wz][i-1]][i-1];
	for(ll i=0;i<e[wz].size();i++)
	{
		ll j=e[wz][i];
		if(j==last) continue;
		dfs(j,wz);
	}
}
ll LCA(ll x,ll y)
{
	if(dep[x]<dep[y]) swap(x,y);
	for(ll i=18;i>=0;i--)
	if(dep[f[x][i]]>=dep[y]) x=f[x][i];
	if(x==y) return x;
	for(ll i=18;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
	return f[x][0];
}
ll query(ll n1,ll n2,ll la1,ll la2,ll l,ll r,ll shu)
{
	if(l==r) return l;
	ll tzy=tr[tr[n1].l].gs+tr[tr[n2].l].gs-tr[tr[la1].l].gs-tr[tr[la2].l].gs;
	ll mid=(l+r)/2;
	if(tzy>=shu) return query(tr[n1].l,tr[n2].l,tr[la1].l,tr[la2].l,l,mid,shu);
	return query(tr[n1].r,tr[n2].r,tr[la1].r,tr[la2].r,mid+1,r,shu-tzy);
}
int main()
{
	scanf("%lld %lld",&n,&m);
	for(ll i=1;i<=n;i++)
	{
		scanf("%d",&a[i].x);
		a[i].pos=i;
	}
	for(ll i=1;i<n;i++)
	{
		scanf("%d %d",&u,&v);
		e[u].push_back(v);
		e[v].push_back(u);
	}
	sort(a+1,a+n+1,cmp1);
	for(ll i=1;i<=n;i++)
	re[i]=a[i].x,a[i].x=i;
	sort(a+1,a+n+1,cmp2);
	dfs(1,0);
	for(ll i=1;i<=m;i++)
	{
		scanf("%d %d %d",&u,&v,&k);
		u=(u^ans);
		ans=re[query(rt[u],rt[v],rt[LCA(u,v)],rt[f[LCA(u,v)][0]],1,n,k)];
		printf("%d\n",ans);
	}
	return 0;
} 

标签:持久,shu,线段,tr,节点,return,树上,ll,gs
From: https://www.cnblogs.com/pengchujie/p/17658946.html

相关文章

  • 可持久化字典树
    例题传送门:异或运算还不错的题既然要异或运算,我们可以想到按位枚举,用字典树去存。既然要找第\(k\)大,我们可以想到主席树。所以这题就是:可持久化字典树考虑到这题\(n,p\)较小,可以直接枚举,而\(m\)较大,我们可以用可持久化字典树去存\(y_i\),查询的时候就模拟字典树的查询,......
  • P2824 排序(二分答案加线段树)
    传送门很巧妙的一个题直接排序肯定会\(T\)飞我们发现问题只有一个:第\(q\)个位置上的数字不难想到从这里入手,二分答案,考虑第\(q\)个位置上的数字是什么,不妨设他为\(x\)然后把大于等于\(x\)的数变成\(1\),小于\(x\)的数变为\(0\),把他转换为一个\(01\)排序问题:对于区间\([l,r]\)......
  • 树上启发式合并
    与其说树上启发式合并是一种算法,不如说是一种思想。它在于通过”小的并入大的“保证复杂度,从而解决很多看似无法做的问题。论纯用树上启发式合并的题很少,但是很多题却可以用树上启发式合并去解决。模板求解的问题往往具有如下性质:每颗子树都有要记录的信息,信息的数量和子树大......
  • 线段树+动态开点权值线段树+主席树学习笔记
    线段树一般用于维护符合结合律的信息。可以用于求区间最大值区间和区间最小值最大子段和甚至于最大负数最小正数之类的信息。事实上线段树只有你想不到,很少有做不到的,算是相当常用的数据结构。下面将结合个人理解和具体题目来讲一讲线段树。[https://www.luogu.com.cn/proble......
  • 树上启发式合并
    树上启发式合并与其说树上启发式合并是一种算法,不如说是一种思想。它在于通过”小的并入大的“保证复杂度,从而解决很多看似无法做的问题。论纯用树上启发式合并的题很少,但是很多题却可以用树上启发式合并去解决。模板求解的问题往往具有如下性质:每颗子树都有要记录的信息,信......
  • 【主席树】洛谷 P3834 可持久化线段树 2
    【主席树】洛谷P3834可持久化线段树2题目链接:https://www.luogu.com.cn/problem/P3834主席树是可持久化线段树的一种,也叫做可持久化权值线段树,主要可以用来O(logn)求静态区间的第k小数。总所周知,普通线段树每次修改会遍历logn个点,那么我们在每次修改时都把这logn个点复制一份......
  • Redis-持久化的学习
    持久化-rdbredis.conf中已经自动配置好了持久化设置,但我们可以改为自己需要的设置。当条件触发时会在同级文件夹内生成dump.rdb文件(快照)。 触发条件:1:满足config中设置的触发条件2:使用flushall命令3:退出redis,也会自动生成dump.rdb  如何打开rdb文件?在redis中输入conf......
  • 可持久化线段树标记永久化?可刺激化修道士表舅已经黑!
    关于可刺激化修道士表舅已经黑。因为傻逼lxd告诉我我的表舅已经黑写法是错误的,所以稀里糊涂的让他改成了他的那种写法。但是我的也是对的。比如区间加和区间查和,维护一个\(tag\),表示表舅的值。然后在区间加的时候,经过的区间的\(sum\)的值可以直接加,但是只有在if(x<=l&......
  • 线段树
    线段树vs树状数组代码长度:树状数组段可扩展性:线段树强,二树状数组仅局限于和的处理思维难度:线段树简单比如区查区改树状数组还要打开多项式搞延迟标记:为了处理当修改区间是\([1,n]\)时所有节点都要被修改一遍的情况如果修改区间覆盖当前区间,那么这颗子树之内所有节点......
  • GEO,持久化方案,主从复制,
    目录1GEO地理位置信息1持久化方案1.1RDB1.2aof方案1.3混合持久化2主从复制原理和方案3哨兵高可用1集群原理及搭建1.1集群搭建1.2集群扩容1.3集群缩容1GEO地理位置信息#GEO(地理信息定位):存储经纬度,计算两地距离,范围等 -根据经纬度---》确定具体地址的---》高德开放a......