HDU 5266 pog loves szh III (线段树+在线LCA转RMQ)
题目地址:HDU 5266
这题用转RMQ求LCA的方法来做的很easy,仅仅须要找到l-r区间内的dfs序最大的和最小的就能够。那么用线段树或者RMQ维护一下区间最值就能够了。然后就是找dfs序最大的点和dfs序最小的点的近期公共祖先了。
代码例如以下:
#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
using namespace std;
#define LL __int64
#define pi acos(-1.0)
#define root 1, n, 1
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
#pragma comment(linker, "/STACK:1024000000")
const int mod=1e4+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
const int MAXN=300000+10;
int fir[MAXN], F[MAXN<<1], tot, deg[MAXN], rmq[MAXN<<1];
int head[MAXN], cnt, n;
int dp[MAXN<<1][30];
int Max[MAXN<<2], Min[MAXN<<2], q_max, q_min;
struct node
{
int u, v, next;
}edge[MAXN<<1];
void add(int u, int v)
{
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void init()
{
memset(head,-1,sizeof(head));
cnt=tot=0;
}
void dfs(int u, int dep, int fa)
{
F[++tot]=u;
rmq[tot]=dep;
fir[u]=tot;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa) continue ;
dfs(v,dep+1,u);
F[++tot]=u;
rmq[tot]=dep;
}
}
struct ST
{
int i, j;
void init()
{
for(i=1;i<=tot;i++) dp[i][0]=i;
for(j=1;(1<<j)<=tot;j++){
for(i=1;i<=tot-(1<<j)+1;i++){
dp[i][j]=rmq[dp[i][j-1]]<rmq[dp[i+(1<<j-1)][j-1]]?dp[i][j-1]:dp[i+(1<<j-1)][j-1];
}
}
}
int Query(int l, int r)
{
if(r<l) swap(l,r);
int k=0;
while((1<<k+1)<=r-l+1) k++;
return rmq[dp[l][k]]<rmq[dp[r+1-(1<<k)][k]]?
dp[l][k]:dp[r+1-(1<<k)][k];
}
}st;
void PushUp(int rt)
{
Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
Min[rt]=min(Min[rt<<1],Min[rt<<1|1]);
}
void Build(int l, int r, int rt)
{
if(l==r){
Max[rt]=Min[rt]=fir[l];
return ;
}
int mid=l+r>>1;
Build(lson);
Build(rson);
PushUp(rt);
}
void Query(int ll, int rr, int l, int r, int rt)
{
if(ll<=l&&rr>=r){
q_max=max(q_max,Max[rt]);
q_min=min(q_min,Min[rt]);
return ;
}
int mid=l+r>>1;
if(ll<=mid) Query(ll,rr,lson);
if(rr>mid) Query(ll,rr,rson);
}
int main()
{
int q, u, v, l, r, i;
while(scanf("%d",&n)!=EOF){
init();
for(i=1;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,0,-1);
st.init();
Build(root);
scanf("%d",&q);
while(q--){
scanf("%d%d",&u,&v);
if(u>v) swap(u,v);
q_min=INF;
q_max=0;
Query(u,v,root);
//printf("%d %d\n",q_min,q_max);
printf("%d\n",F[st.Query(q_min,q_max)]);
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
2015-03-10 mysql 加入列,改动列,删除列。
2015-03-10 Effective JavaScript Item 21 使用apply方法调用函数以传入可变參数列表
2015-03-10 EJB学习笔记
2015-03-10 PID教程
2015-03-10 C/C++中各种类型int、long、double、char表示范围(最大最小值)
2015-03-10 Hibernate 学习教程
2015-03-10 计算机能够这样玩—自我学习,自我思维,自我工作(编程)