CF983E NN country 题解

news/2025/1/8 19:49:13/文章来源:https://www.cnblogs.com/peiwenjun/p/18660431

题目描述

给定 \(n\) 个点的树和 \(m\) 条路线,每条路线连接路径 \((u,v)\) 之间的所有点。

\(q\) 次询问,从 \(u\)\(v\) 至少要经过多少条路线。

数据范围

  • \(2\le n\le 2\cdot 10^5,1\le m\le 2\cdot 10^5,1\le q\le 2\cdot 10^5\)

时间限制 \(\texttt{3s}\) ,空间限制 \(\texttt{256MB}\)

分析

容易想到的贪心策略是每一步跳到可到达的深度最小的点。

用倍增加速上述过程,预处理 \(f_{u,i}\) 表示从 \(u\) 出发跳 \(2^i\) 步能到达的最浅点。

什么时候贪心会出问题?记 \(p=lca(u,v)\) ,只要跳完以后仍在子树内就无脑跳(一定最优),如果从 \(x,y\) 再跳一步就要到 \(p\) 及其祖先,但是 \(x,y\) 在同一条路线上,那么只需要一条路径(原策略需要两条)。

注意如果 \((u,v)\) 是一条直上直下的链就不需要考虑这种情况。

于是问题转化为如何判断 \((x,y)\) 是否在同一条路径上,这等价于判断是否存在路线 \((u,v)\) 满足 \(u\)\(x\) 子树内, \(v\)\(y\) 子树内。

\((u,v)\) 看成二维平面上的点 \((dfn_u,dfn_v),(dfn_v,dfn_u)\) ,只需判断横坐标 \([dfn_x,dfn_x+sz_x-1]\) ,纵坐标 \([dfn_y,dfn_y+sz_y-1]\) 的矩形框中是否有点。

这是经典二维数点问题,离线扫描线 \(+\) 树状数组解决。

时间复杂度 \(\mathcal O((n+m+q)\log n)\)

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int m,n,p,q,u,v,cnt;
int d[maxn],fa[maxn],sz[maxn],son[maxn];
int dfn[maxn],top[maxn];
int f[maxn][18];
int c[maxn],res[maxn],val[maxn];
vector<int> g[maxn],h[maxn];
struct oper
{int l,r,op,id;
};
vector<oper> vec[maxn];
void dfs1(int u)
{sz[u]=1;for(auto v:g[u]){d[v]=d[u]+1,fa[v]=u,dfs1(v),sz[u]+=sz[v];if(sz[v]>sz[son[u]]) son[u]=v;}
}
void dfs2(int u,int f)
{dfn[u]=++cnt,top[u]=f;if(son[u]) dfs2(son[u],f);for(auto v:g[u]) if(v!=son[u]) dfs2(v,v);
}
int lca(int u,int v)
{while(top[u]!=top[v]) d[top[u]]>d[top[v]]?u=fa[top[u]]:v=fa[top[v]];return d[u]<d[v]?u:v;
}
void add(int x,int v)
{while(x<=n) c[x]+=v,x+=x&-x;
}
int query(int x)
{int res=0;while(x) res+=c[x],x-=x&-x;return res;
}
int main()
{scanf("%d",&n);for(int i=2;i<=n;i++) scanf("%d",&u),g[u].push_back(i);d[1]=1,dfs1(1),dfs2(1,1);for(int i=1;i<=n;i++) f[i][0]=i;scanf("%d",&m);while(m--){scanf("%d%d",&u,&v),p=lca(u,v);f[u][0]=min(f[u][0],p),f[v][0]=min(f[v][0],p);h[dfn[u]].push_back(dfn[v]),h[dfn[v]].push_back(dfn[u]);}for(int u=n;u>=1;u--) for(auto v:g[u]) f[u][0]=min(f[u][0],f[v][0]);for(int i=1;i<18;i++) for(int u=1;u<=n;u++) f[u][i]=f[f[u][i-1]][i-1];scanf("%d",&q);for(int i=1;i<=q;i++){scanf("%d%d",&u,&v),p=lca(u,v);for(int j=17;j>=0;j--){if(f[u][j]>p) u=f[u][j],res[i]+=1<<j;if(f[v][j]>p) v=f[v][j],res[i]+=1<<j;}if(f[u][0]>p||f[v][0]>p) res[i]=-1;else{if(u==p||v==p) res[i]++;else{vec[dfn[u]-1].push_back({dfn[v],dfn[v]+sz[v]-1,-1,i});vec[dfn[u]+sz[u]-1].push_back({dfn[v],dfn[v]+sz[v]-1,1,i});}}}for(int i=1;i<=n;i++){for(auto p:h[i]) add(p,1);for(auto [l,r,op,id]:vec[i]){val[id]+=(query(r)-query(l-1))*op;if(op==1) res[id]+=val[id]?1:2;}}for(int i=1;i<=q;i++) printf("%d\n",res[i]);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/866036.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(2025自测有效!)全网最好的python配置教程【非常非常适合小白】

前几天我的电脑刚刚重装,把python重新配置了一下。 1.Python环境部署Python3 可应用于多平台包括 Windows、Linux 和 Mac OS X。 Python官网:https://www.python.org/ 进入官网在导航栏选择Dowmloads,选择所使用的系统(以Windows为例) 进入Windows下载页之后选择需要下载的…

写一个支持折叠、有缩进、代码高亮、离线的,方便部署的、易用的、优雅的json格式化查看工具(附html完整代码)

缘由 网上的在线json格式化有很多,但我是个有追求的人。在线的很难同时支持折叠、有缩进线、代码高亮、离线的,方便部署的、易用的、不请求后端(为了安全)的json格式化工具。 去Github上找项目,华而不实的东西占半个屏幕,格式化json要点好几下,一个json格式化工具npm安装…

AGC041F Histogram Rooks

我不知道啊,我只是觉得容斥很好玩。一个朴素的想法是容斥:考虑钦定 \(S\) 集合的位置没有被车覆盖,则答案是 \((-1)^{|S|}2^{c}\),其中 \(c\) 是可以放车的位置,可以直接 dp 做到 \(\mathrm{O}(2^n \text{poly}(n))\),但是难以优化。 延续容斥的想法,注意到钦定一个位置…

rust学习十六.1、并发-乱弹和一个简单并发例子

如书本作者所言,并发编程在绝大部分语言中,都是相对复杂和困难的。 所以,涉及的内容会相对多一些,所涵盖的内容绝对不是几篇文章所可以容纳的。 权当一个乱弹琴! 和此系列的其它文章一样,本文的内容绝大部分来自于相关书籍,本人做了一些摘裁的工作,取我所需!一、无畏并…

解决jenkins git 拉取代码超时问题

jenkins默认的是时间是10分钟,在git fetch时候超过10分钟了就报错失败了,可在项目源码管理 新增 advance clone behaviours

Java Bluetooth 蓝牙通讯 BlueCove 扫描附近的蓝牙设备

目录BlueCove项目概述BlueCove API架构API的设计原则和实现方式关键类和方法的功能描述测试代码获取本机(PC)蓝牙扫描蓝牙 BlueCove项目概述 BlueCove是一个开源的蓝牙协议栈实现,旨在为Java开发者提供一个全面的、易于使用的API,从而在应用程序中实现蓝牙功能。该项目支持多…

英伟达世界基础模型 Cosmos,教 AI 理解物理世界;阿里通义与雷鸟合作推出 AI 眼镜丨 RTE 开发者日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的新闻」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文章 」、「有看点的 会议 」,但内容仅代表编辑的…

.NET 窗口置于最顶层

本文介绍如何将窗口置于最顶层,以及解决在顶层显示时对锁屏登录界面的影响。用于实现类似Launcher、系统工具等应用需要窗口层级比Windows开始菜单以及置顶任务栏还要高的场景 一般情况下的窗口置顶,可以设置WPF窗口属性Topmost=true 也可以使用WIN32-SetWindowPos函数SetWin…

汽修行业的智能化转型:AI赋能员工培训SOP策略

随着智能化技术的飞速发展,汽修行业也迎来了前所未有的变革机遇。在这一背景下,如何构建高效、标准化的员工培训SOP(Standard Operating Procedure)策略,成为汽修企业提升竞争力、实现智能化转型的关键。本文将探讨智能AI在汽修行业员工培训SOP策略构建中的应用,特别是提…

智慧医疗新纪元:帮助中心引领的智能化转型之路

在科技日新月异的今天,智慧医疗已经成为医疗领域发展的重要趋势。智慧医疗不仅意味着医疗设备的智能化,更代表着整个医疗服务流程的数字化转型。在这一变革过程中,如何有效利用帮助中心驱动医疗机构的转型与升级,成为了一个值得深入探讨的课题。本文将探讨智慧医疗的智能跃…

sqlalchemy.exc.OperationalError

最后发现是 密码中含特殊字符@导致的连接报错其他参考: sqlalchemy.exc.OperationalError通常指示Python应用程序与数据库之间的连接出现问题。这里有一些可能的原因和解决方案:数据库连接参数错误:检查你的数据库连接字符串(DSN)。确保主机名、端口、数据库名称、用户名和…

五大优势:开源AI视频监控助力精准打击公租房非法倒卖行为

一. 用户痛点:传统监控面临的挑战与隐患 公租房作为社会保障性住房的一种,旨在为低收入群体提供基本的居住保障。然而,随着市场上房地产倒卖行为的增多,许多公租房被非法转租或倒卖给非资格居民,导致公租房资源流失、社会公平受损。政府在这方面的监管面临诸多困难,传统的…