首页 > 其他分享 >一种简洁且常数较小的在线树上k级祖先求解.

一种简洁且常数较小的在线树上k级祖先求解.

时间:2023-12-05 20:56:25浏览次数:36  
标签:std 简洁 求解 int dfn u32 ti using 常数

起因是有人在la群问
已知u是v的祖先,求u到v路径上第一个点.
怎么写比较简单.

突然想起很久之前我在la板子上写过一个题解区里没有看到的简洁做法.

有一个不难证明的结论,一个节点u的k级祖先v对应深度的所有节点中dfn序中小于等于u的最后一个点.

考虑dfn序的性质,u一定在v所在的子树的这段区间中,因此得证.

开vector然后二分即可.

复杂度 O(n+qlogn) 常数较小(一次跑不满的二分).

code
#include<bits/stdc++.h>
using i64=long long;
using u32=unsigned;
using std::cin;
using std::cout;
u32 s;
u32 get(u32 x){
	x^=x<<13;
	x^=x>>17;
	x^=x<<5;
	return s=x; 
}
void solve(){
	int n,q;
	cin>>n>>q>>s;
	std::vector<int> fa(n+1),dfn(n+1),rnk(n+1),dep(n+1);
	std::vector<std::vector<int> > G(n+1),Z(n+1);
	for(int i=1;i<=n;++i){
		cin>>fa[i];
		G[fa[i]].emplace_back(i);
	}
	int ti=0;
	auto dfs=[&](auto&&self,int u,int d)->void{
		rnk[ti]=u,dfn[u]=ti,dep[u]=d;
		Z[d].emplace_back(ti),++ti;
		for(auto to:G[u]){
			self(self,to,d+1);
		}
	};
	dfs(dfs,0,0);
	i64 ans=0,las=0;
	for(int i=1;i<=q;++i){
		int x=(get(s)^las)%n+1,k=(get(s)^las)%dep[x];
		las=rnk[*prev(upper_bound(Z[dep[x]-k].begin(),Z[dep[x]-k].end(),dfn[x]))];
		ans^=i*las;
	}
	cout<<ans;
}
int main(){
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	solve();
	return 0;
}
// https://www.luogu.com.cn/problem/P5903

标签:std,简洁,求解,int,dfn,u32,ti,using,常数
From: https://www.cnblogs.com/QedDust/p/17878120.html

相关文章

  • 2023-12-02:用go语言,如何求模立方根? x^3=a mod p, p是大于等于3的大质数, a是1到p-1范围
    2023-12-02:用go语言,如何求模立方根?x^3=amodp,p是大于等于3的大质数,a是1到p-1范围的整数常数,x也是1到p-1范围的整数,求x。p过大,x不能从1到p-1遍历。答案2023-12-02:灵捷3.5大体步骤如下:1.判断是否存在模立方根。有0,1,3个根这三种情况。1.1.求p-1和3的最大公约数gcd(p-1,3)......
  • 《代码简洁之道》读后感三
    后半部分更深入地探讨了良好设计的重要性。书中提及的单一职责原则、开闭原则等设计原则,对于构建灵活、可扩展、易维护的系统至关重要。通过这些设计原则,能够更好地组织代码、减少耦合,使得代码更易于理解和修改。代码演化与重构:书中强调了代码是随着时间演化的,并提出了重构的概......
  • 求解--JFinal项目启动之后在浏览器显示不了的问题(未解决)
    问题描述问题解决......
  • 数组(2)数组运算及典例(求解素数的方法)
    <1>数组运算1)数组的集成初始化1.形式示例1-inta[]={1,2,3...};2-inta[13]={2};————第一个单元内中的a0=2,剩下的单元都默认赋为0;2.集成初始化时的定位——仅适用于C99举例:inta[10]={[0]=2,[2]=3,6,};特点:用[n]在初始化数据中给出定位;没有定位的数......
  • 求解--如何把图片的base64编码转换成图片(未解决)
    问题描述将图片弄好之后,并且显示我弄成功了,但是就是找不到图片保存到哪里了;然后发现可以将base64编码转换成图片,但是不会转~~~求解救呀~~~问题解决未解决!!!......
  • 线性规划——Pyhton线性规划求解库PULP的使用
    PuLP是一个用于线性规划(LP)、整数线性规划(ILP)和混合整数线性规划(MILP)问题的Python库。PuLP的全称是"PythonforMathematicalProgramming",它提供了一个简单而强大的工具,使得用户能够定义优化问题、构建数学模型并使用不同的求解器进行求解。PuLP的主要特点之一是其易用性。它允许......
  • 员工管理系统简洁版
    【一】需求介绍用户可以注册,并将注册信息临时保存起来,登陆时可根据指定用户名或密码进行登陆设定好用户名和密码,用户通过输入指定的用户名和密码进行登陆最大尝试次数:用户最多尝试猜测3次最大尝试次数后:如3次后,问用户是否继续登陆如果回答Y或y,就再给3次机会,提示【还剩最后......
  • 用户登录注册简洁版
    【一】需求介绍设定好用户名和密码,用户通过输入指定的用户名和密码进行登陆最大尝试次数:用户最多尝试猜测3次最大尝试次数后:如3次后,问用户是否继续登陆如果回答Y或y,就再给3次机会,提示【还剩最后三次机会】3次都猜错的话登录结束如果回答N或n,登陆结束!如果格式输入错误,提示......
  • 159.102 C++问题求解
    一家生产纽扣的工厂给了你一份合同。工厂识别损坏的按钮,使其不会提供给商店。这家工厂有一台可以拍摄纽扣的照片。这台相机只能用黑白(没有颜色),分辨率不是很高很好,但这不是问题。你的工作是编写一个C++程序,识别照片中任何损坏的按钮。你需要生成一个图像,在每个按钮周围显示一个框。......
  • 单链表建表,倒置,遍历(不使用Class,简洁易懂)
    在C++中通过递归方法实现单链表倒置初始化列表structListNode{ intval; LiseNode*next; ListNode(intx):val(x),next(NULL){}};遍历voidquery_node(){ node*p=head; while(p!=NULL){ cout<<p->data<<''; p=p->nxt; } cout<<endl;}建表(......