P11364 [NOIP2024] 树上查询

news/2025/2/6 21:08:44/文章来源:https://www.cnblogs.com/wingheart/p/18701249

P11364 [NOIP2024] 树上查询

题意

给你一棵 \(n\) 个结点,以 \(1\) 为根的树。定义 \(\text{LCA}^*(l,r)\) 表示编号在 \([l,r]\) 间的所有的结点的最近公共祖先。有 \(q\) 次询问,每次给出 \(l,r\),问满足 \([l',r'] \subseteq [l,r]\) 且区间长度至少为 \(k\) 的最大的 \(\text{dep}_{\text{LCA}^*(l',r')}\) 是多少。

\(n,q \le 5 \times 10^5\)

思路

不难发现 \(\text{LCA}^*(l,r)\) 就是 \(\min_{i=l}^{r-1} \text{dep}_{\text{lca}_{i,i+1}}\),特判 \(l=r\) 的情况。可以根据欧拉序求 \(\text{LCA}\) 或者随便理解。

于是我们有了朴素的 \(O(qn^2)\) 暴力:预处理相邻 \(\text{LCA}\) 的深度,每次询问枚举合法的 \(l',r'\) 然后 st 表做。


\(d_i = dep_{lca_{i,i+1}}\),考虑把 \(d_i\) 建笛卡尔树,以便分析性质做一些预处理。

每次找出最小的 \(d_i\) 做根。我们要尽量大的答案。一个 \(d_i\) 可以做答案当且仅当 \([l,r]\) 可以选出一个长度至少为 \(k\) 的在子树内的区间,就是和子树表示的区间的交至少长度是 \(k\)。但是不好保证选出的区间一定覆盖了 \(d_i\)

每次找出最大的 \(d_i\) 做根。预处理出每个 \(d_i\) 向左右扩展出的极大区间 \([x_i,y_i]\) 满足 \([x_i,y_i]\) 里面没有比 \(d_i\) 小的数。可以单调栈预处理。

\(d_i\) 可以做答案当且仅当 \([l,r]\)\([x_i,y_i]\) 的交长度至少是 \(k\),且选出来的区间不覆盖 \(d_i\) 也不影响答案。


每次询问,找出最大的合法 \(d_i\)。刻画一下合法状态:

\[y_i-x_i+1 \ge k \land \begin{cases} y_i \le r \land y_i - l +1 \ge k & (y_i \le r)\\ y_i > r \land r-x_i+1 \ge k & (y_i > r) \end{cases} \]

这是三维偏序吗?不是的。可以化简成:

\[\begin{cases} k+l-1 \le y_i \le r \land y_i-x_i \ge k-1 & (1)\\ y_i>r \land x_i \le r-k+1 & (2) \end{cases} \]

式子 \(1\) 可以扫描询问,把满足 \(y_i-x_i \ge k-1\) 的点放进数据结构里,维护 \(y_i\),然后对每个询问查询 \(y_i \in [k+l-1,r]\)\(d_i\) 最大的点。

式子 \(2\) 可以扫描询问,把满足 \(y_i > r\) 的点放进数据结构里,维护 \(x_i\),然后对每个询问查询 \(x_i \le r-k+1\)\(d_i\) 最大的点。

时间复杂度 \(O(n \log n)\)。(\(n,q\) 同阶)

code

#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
namespace wing_heart {constexpr int N=5e5+7;int n,u,v;vector<int> son[N];int fa[N],dfn[N],dep[N],dfn0;int st[30][N],stdep[30][N];int q,l,r,k;void dfs(int u,int f) {dep[u]=dep[f]+1;dfn[u]=++dfn0;st[0][dfn0]=dep[f];stdep[0][u]=dep[u];for(int v : son[u]) if(v^f) dfs(v,u);}void lca_init() {int lg=__lg(n);rep(k,1,lg) for(int i=1;i+(1<<k)-1<=n;i++) st[k][i]=min(st[k-1][i],st[k-1][i+(1<<(k-1))]), stdep[k][i]=max(stdep[k-1][i],stdep[k-1][i+(1<<(k-1))]);}int d[N];int getlca(int u,int v) {int mn=min(dfn[u],dfn[v])+1,mx=max(dfn[u],dfn[v]);int lg=__lg(mx-mn+1);return min(st[lg][mn],st[lg][mx-(1<<lg)+1]);}int stmax(int l,int r) {int lg=__lg(r-l+1);return max(stdep[lg][l],stdep[lg][r-(1<<lg)+1]);}struct node {int id,a,b,c;}x[N<<1];bool cmp1 (node x,node y) {int x1=!x.id ? x.b-x.a : x.c-1, y1=!y.id ? y.b-y.a : y.c-1; return x1==y1 ? x.id < y.id : x1>y1;}bool cmp2 (node x,node y) {return x.b==y.b ? x.id > y.id : x.b > y.b;}int t[N],top;int ans[N];struct seg {int mx[N<<2];void clear() {memset(mx,0,sizeof(mx));}void pushup(int u) { mx[u]=max(mx[u<<1],mx[u<<1|1]); }void insert(int x,int val,int u=1,int l=1,int r=n) {if(l==r) return mx[u]=val, void(0);int mid=(l+r)>>1;if(x<=mid) insert(x,val,u<<1,l,mid);else insert(x,val,u<<1|1,mid+1,r);pushup(u);}int query(int L,int R,int u=1,int l=1,int r=n) {if(l>=L && r<=R) return mx[u];int mid=(l+r)>>1;int s=0;if(L<=mid) s=query(L,R,u<<1,l,mid);if(mid+1<=R) s=max(s,query(L,R,u<<1|1,mid+1,r));return s;}}T;void main() {sf("%d",&n);rep(i,1,n-1) sf("%d%d",&u,&v), son[u].push_back(v), son[v].push_back(u);dfs(1,0);lca_init();rep(i,1,n-1) d[i]=getlca(i,i+1);rep(i,1,n-1) {x[i].c=d[i];while(top && x[t[top]].c>d[i]) x[t[top]].b=i-1, --top;t[++top]=i;}while(top) x[t[top]].b=n-1, --top;per(i,n-1,1) {while(top && x[t[top]].c>d[i]) x[t[top]].a=i+1, --top;t[++top]=i;}while(top) x[t[top]].a=1, --top; sf("%d",&q);rep(i,1,q) {sf("%d%d%d",&l,&r,&k);--r, --k;x[i+n-1]={i,l,r,k};}sort(x+1,x+n+q,cmp1);rep(i,1,n+q-1) {int id=x[i].id,a=x[i].a,b=x[i].b,c=x[i].c;if(!id) {T.insert(b,c);} else {if(!c) {ans[id]=stmax(a,b+1);continue;}ans[id]=T.query(c+a-1,b);}}sort(x+1,x+n+q,cmp2);T.clear();rep(i,1,n+q-1) {int id=x[i].id,a=x[i].a,b=x[i].b,c=x[i].c;if(!id) {T.insert(a,c);} else {if(!c) continue;ans[id]=max(ans[id],T.query(1,b-c+1));}}rep(i,1,q) pf("%d\n",ans[i]);}
}
int main() {#ifdef LOCALfreopen("in.txt","r",stdin);freopen("my.out","w",stdout);#endifwing_heart :: main();
}

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

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

相关文章

社媒风控下的生存法则:云手机如何为Facebook、X(Twitter)账号安全护航

社媒风控下的生存法则:云手机如何为Facebook、X(Twitter)账号安全护航 在社交媒体平台(如Facebook、X/Twitter)风控日益严格的背景下,账号安全成为运营者的核心痛点。平台通过检测设备指纹、IP地址、SIM卡信息等参数,对批量操作、异常登录或虚拟环境进行封号限制。云手机…

还在为标准“头秃”?数字化转型秘籍来了!

数字化浪潮席卷而来,企业都想“乘风破浪”,可标准化管理这块“基石”要是没打牢,小心“翻船”哦!别担心,我们带着标准制修订信息管理系统来拯救你啦!这可不是一般的系统,它能让你的标准化工作从“石器时代”直接跃迁到“赛博朋克”!😫 标准化管理的“老大难”:你中了…

[megatron代码阅读] 2. TP和PP实现

megatron 源码阅读第二篇, 看了TP和PP的对应实现训练并行实现 TensorParallel 张量并行代码路径, 代码路径: megatron/core/tensor_parallel 主要包含Linear / VocabEmbedding / cross_entropy 三部分. Linear 参数初始化 如果是从checkpoint热启, perform_initialization需要打…

2024.2.6鲜花

初探牛顿迭代?推歌 《以恋结缘》 诚、意地の悪い神の所业か? 奇迹?縁?袂触合う不思议 花ひとひら揺れて 不意に宿ってた うなじ解いてく春风 戯れはそこそこに 恋手ほどきしてくだしゃんせ 汤気にほんのり頬染て 夜风に愿ふ …いざ!!蝶と舞ひ花となりて 衣を乱して祓いま…

megatron 2. TP和PP实现

megatron 源码阅读第二篇, 看了TP和PP的对应实现训练并行实现 TensorParallel 张量并行代码路径, 代码路径: megatron/core/tensor_parallel 主要包含Linear / VocabEmbedding / cross_entropy 三部分. Linear 参数初始化 如果是从checkpoint热启, perform_initialization需要打…

【Azure Policy】当Azure策略组中存在多个修正任务时候时的批量处理办法

问题描述 在分配一组策略中包含了很多修正任务时候,从门户上,只能选择一个修正任务执行。 如下图:是否有好的办法,执行全部的修正任务呢?问题解答 从Azure门户的设计来看,只能选择一个修正任务是设计使然。如果想批量执行全部的修正任务,需要使用PowerShell脚本来循环执…

Kotlin空安全

前言 访问空引用的成员变量就会导致空指针异常,在Java中被称作NullPointerException,简称NPE,Kotlin中NPE产生的原因只可能是以下几种:显式调用 throw NullPointerException()使用了!!操作符数据在初始化时不一致,例如:传递一个在构造函数中出现的未初始化的 this 并用于…

Kotlin控制流程

条件与循环 if表达式 Kotlin中的if与Java中的if大致上都差不多,但是Kotlin中没有三元运算符(A ? B : C),可以用if表达式作为代替,例如: Java int a = int a = System.currentTimeMillis() % 2 == 1L ? 1 : 0; Kotlin val a = if (System.currentTimeMillis() % 2 == 1L…

第一次用Markdown

标题 标题2 标题3 标题4 字体 字体 字体姓名 性别 年龄张三 男 20![das]() baidu

【测试基础】web3.0介绍

web3.0介绍 Web3.0也被称为下一代互联网,是对当前互联网(Web2.0)的演进和升级。其目标是实现一个更加去中心化、安全、用户拥有数据主权且具有更好互操作性的互联网环境。Web3.0的核心技术包括区块链、智能合约和加密货币等。 web2.0与web3.0区别 Web2.0和Web3.0的主要区别在…

区块链原理、技术与实践

区块链介绍 区块链是一种分布式账本技术,允许多个参与者共同维护一个不断增长的数据记录列表,每个区块包含一系列交易记录,并通过密码学方法与前一个区块链接起来,形成一个不可篡改和不可逆的链条。 这种基于共识的机制使得区块链具有高度的安全性和透明性。 区块链与传统W…

《高效能人士的七个习惯》

情感账户 勇气和体谅 大石头 自传式回应、同理心倾听:用你的话反映他们的感受和意思,而不是去评论、去判断是否正确