NOIP2024T4 copy

news/2025/2/27 18:12:17/文章来源:https://www.cnblogs.com/rhineofts/p/18741630

用到的所有 trick 应该都是比较常用的?可以作为一道综合练习题。

该做法来自洛谷第一篇题解。

首先是经典引理:区间 lca 等于「区间相邻点 lca 」中深度最小的那个点(区间长度大于 \(1\))。

证明:

显然区间 \([l, r]\) 的 lca 深度小于等于上面的东西 (\(dep_{\operatorname{lca}(u, v)} \le dep_u\))。因此只需证明上面这个东西能取到区间 lca。

考虑区间 lca \(u\)。若 \(u\) 本身就在区间中,则显然能取到。否则:这个区间中的点一定可以按在 \(u\) 的哪个子树划分成严格大于 \(1\) 个集合。那么一定存在相邻两个点,它们不在同一集合中。那么它们的 lca 就是 u。

这里用了分析 lca 的一个经典技巧:\(x, y\) 一定位于 lca(x, y) 的两个不同子树中(不考虑 x,y 为祖先后代关系)。

判掉 \(k=1\) 的情况后,整个问题就完全成了一个序列问题:每次询问给定一个区间 \([l, r]\),求 \(\max_{[x, y] \subseteq [l, r] ∧ |[x, y]| = k} \left(\min_{i\in [x, y]}a_i \right)\)。也就是长度为 \(k\) 的子区间最小值的最大值。

这个问题形式就很简洁。下面处理这个问题的技巧则更精妙:

首先是一个称为支配对的思想:只考虑对答案有本质贡献的点对或其他什么东西,而如果这样的东西很少(比如说 \(O(n)\)\(O(n\log n)\),比起最初的 \(O(n^2)\) 的点对),能够用数据结构维护,就做完了。

对于这个问题,定义支配对为区间 min 为某个值的极大区间。考虑区间 min 在哪个点处取到,可以发现这个东西就是这个点前面/后面第一个比它小的数形成的开区间。这个东西很好用单调栈维护。同时也说明了支配对不会超过 \(n\)

现在我们提取出一堆带权(lca 深度/区间 min)支配区间。问题转化为:对于每个查询区间 \([ql, qr]\),求出和它交集大于等于 \(k\) 的所有区间的权的最大值。

我们分两类讨论:

对于 \(R \ge qr\) 的情况,限制为 \(R \ge qr ∧ L \le qr - k + 1\)(题目保证 \(k \le qr - ql + 1\)

k 只和 \(ql, qr\) 相关,第一个限制可以对 \(R\) 做扫描线,后面的限制转化为查询前缀 min,树状数组维护。

对于 \(R < qr\) 的情况,限制为 \(R - L + 1 \le k ∧ R \ge ql + k - 1 ∧ R < qr\)。第一个限制仍然扫描线,后面两个限制关于 \(R\) 是一段区间,线段树维护。

做完了,\(O(n\log n)\)!!!

template <typename T1, typename T2>
bool ckmax(T1& LHS, const T2& RHS) {return LHS < RHS ? LHS = RHS, true : false;
}
template <typename T1, typename T2>
bool ckmin(T1& LHS, const T2& RHS) {
const int N = 5e5 + 10;
int a[N], dep[N], b[N];
vi adj[N];
int n; namespace fenwick {//vi int t[N]; // int n;// fenwick() = default;// fenwick(int _n) {//     n = _n; t.resize(n + 1);// }int lb(int x) {return x & (-x);}void add(int pos, int x) {while (pos <= n) {ckmax(t[pos], x); pos += lb(pos);}}int query(int pos) {int res = 0;while (pos) {ckmax(res, t[pos]); pos -= lb(pos);}return res;}
};namespace seg {int w[N << 2];#define ls (u << 1)#define rs (u << 1 | 1)#define mid ((l + r) >> 1)void pushup(int u) {ckmax(w[u], max(w[ls], w[rs]));}void update(int u, int l, int r, int pos, int x) {if (l == r) ckmax(w[u], x);else {if (pos <= mid) update(ls, l, mid, pos, x);else update(rs, mid + 1, r, pos, x);pushup(u);}}int query(int u, int l, int r, int ql, int qr) {if (ql <= l and r <= qr) return w[u];if (qr < l or r < ql) return 0;return max(query(ls, l, mid, ql, qr), query(rs, mid + 1, r, ql, qr));}
}namespace cornercase {int st[19][N];int Max(int l, int r) {int d = __lg(r - l + 1);return max(st[d][l], st[d][r - (1 << d) + 1]);}void init() {F (i, 1, n) st[0][i] = dep[i];F (i, 1, __lg(n)) {F (j, 1, n - (1 << i) + 1) {st[i][j] = max(st[i - 1][j], st[i - 1][j + (1 << i - 1)]);}}}
}namespace LCA {int tot;int st[19][N], dfn[N];void dfs(int u, int fa) {dep[u] = dep[fa] + 1;dfn[u] = ++tot; st[0][tot] = fa;for (int v : adj[u]) {if (v == fa) continue;dfs(v, u);}}int Min(int u, int v) {return dfn[u] < dfn[v] ? u : v;}void init() {F (i, 1, __lg(n)) {F (j, 1, n - (1 << i) + 1) {st[i][j] = Min(st[i - 1][j], st[i - 1][j + (1 << i - 1)]);}}}int lca(int u, int v) {if (u == v) return u;u = dfn[u], v = dfn[v];if (u > v) swap(u, v);u++;int d = __lg(v - u + 1);return Min(st[d][u], st[d][v - (1 << d) + 1]);}
} using LCA::lca;struct Query {int l, r, k, id;
} q[N]; int OoO;struct interval {int l, r, dep;
} h[N]; int ovo;int ans[N];void solve() {cin >> n;F (i, 1, n - 1) {int u, v; cin >> u >> v; adj[u].pb(v); adj[v].pb(u);}LCA::dfs(1, 0); LCA::init();// debug(pair<int*, int*>(dep + 1, dep + n + 1));cornercase::init();int Q; cin >> Q;F (i, 1, Q) {int l, r, k; cin >> l >> r >> k;if (k == 1) {debug(i);ans[i] = cornercase::Max(l, r);} else {q[++OoO] = {l, r - 1, k - 1, i};}}n--;F (i, 1, n) {b[i] = dep[lca(i, i + 1)];}vi stk(n + 1); int top = 0;vi L(n + 1), R(n + 1);F (i, 1, n) {   while (top and b[stk[top]] >= b[i]) {top--;}L[i] = stk[top] + 1;stk[++top] = i;} top = 0;DF (i, n, 1) {while (top and b[stk[top]] >= b[i]) {top--;}R[i] = top ? stk[top] - 1 : n;stk[++top] = i;}// debug(pair<int*, int*>(b + 1, b + 1 + n));// F (i, 1, n) {//     debug(pii(L[i], R[i]));// }F (i, 1, n) {if (b[i] != b[i - 1]) {h[++ovo] = {L[i], R[i], b[i]};}}sort(h + 1, h + 1 + ovo, [&](const auto& lhs, const auto& rhs) {return lhs.r > rhs.r;});// fenwick bit(n);sort(q + 1, q + 1 + OoO, [&](const auto& lhs, const auto& rhs) {return lhs.r > rhs.r;});F (i, 1, OoO, j = 1) {while (j <= ovo and h[j].r >= q[i].r) {fenwick::add(h[j].l, h[j].dep); j++;}ckmax(ans[ q[i].id ], fenwick::query( q[i].r - q[i].k + 1 ));}sort(h + 1, h + 1 + ovo, [&](const auto& lhs, const auto& rhs) {return lhs.r - lhs.l > rhs.r - rhs.l;});sort(q + 1, q + 1 + OoO, [&](const auto& lhs, const auto& rhs) {return lhs.k > rhs.k;});    F (i, 1, OoO, j = 1) {while (j <= ovo and h[j].r - h[j].l + 1 >= q[i].k) {seg::update(1, 1, n, h[j].r, h[j].dep); j++;}ckmax(ans[ q[i].id ], seg::query(1, 1, n, q[i].l + q[i].k - 1, q[i].r));}F (i, 1, Q) {cout << ans[i] << "\n";}
}

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

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

相关文章

[MoE] Deepseek的All-to-all通信: DeepEP代码解读

[MoE] Deepseek的All-to-all通信: DeepEP代码解读 前言 最近,Deepseek开源了一系列MoE的优化技术,让我们看到了AI infra的强大之处。其中,第二天发布的DeepEP则是针对MoE中EP的all-to-all通信进行了优化。 我最近也在关注MoE和all-to-all,之前的MoE普遍使用NCCL的p2p通信进…

Java泛型上下界

有如下类的继承关系 // okFruit apple = new Apple(); List<Fruit> plate = new ArrayList<Apple>(); 它会在Idea里报红线,运行会报错:java: 不兼容的类型: java.util.ArrayList<Apple>无法转换为java.util.List<Fruit>,显然在集合间不存在继承引用…

Redis复习-通信协议、内存回收

通信协议 RESP协议 Redis是一个CS架构的软件,通信一般分两步(不包括pipeline和PubSub): 1.客户端(client)向服务端(server)发送一条命令 2.服务端解析并执行命令,返回响应结果给客户端 因此客户端发送命令的格式、服务端响应结果的格式必须有一个规范,这个规范就是通…

vi和vim快捷键

vi和vim常用的一些快捷键分类 快捷键 说明模式切换 i 进入插入模式(在光标前插入文本)。a 进入插入模式(在光标后插入文本)。o 在当前行下方插入新行并进入插入模式。O 在当前行上方插入新行并进入插入模式。Esc 退出插入模式,返回命令模式。: 进入命令模式(用于输入命令…

Go红队开发—语法补充

之前有师傅问这个系列好像跟红队没啥关系,前几期确实没啥关系,因为这都是进行红队工具开发的前置知识点,对于我个人强迫症而言只是想让这个系列更加完善而已,所以前置知识也加进去了,有GO只是的大佬可以等下一期哈!感谢支持。目录错误控制使用自定义错误类型错误包装erro…

Security认证失败逻辑

通过一系列的过滤器最终走到 FilterSecurityInterceptor package org.springframework.security.access.vote;public class AffirmativeBased extends AbstractAccessDecisionManager {public AffirmativeBased(List<AccessDecisionVoter<? extends Object>> deci…

关于书店管理系统的二次开发

一、来源 来自同学期末大作业。实现了基本的书店业务功能,包括书本信息管理、客户信息管理、购物车操作以及订单生成与保存等。 二、运行环境 + 运行结果的截图 操作系统:Windows 11 开发工具:Visual Studio 2022// BookStore.h点击查看代码 #ifndef BOOKSTORE_H #define BO…

CNC数控机床运行状态参数采集联网 对接软件MES 系统

IP 端口 TCP端口 流程任务 当前位置或者目标位置及描述 状态 需要接口内容 请求地址-AGV 请求AGV参数 请求AGV返回信息 PLC-地址 写入PLC值 读取PLC值 EDM-地址 写入EDM值 读取EDM值进入上下料进程 进入EDM上料台动作-动作 即将进入EDM上料台 "1.达…

Redis+Docker集群部署

机器故障了怎么办? Redis 是内存数据库,我们知道可以通过持久化机制,保存快照或者保存记录日志的方式,将数据持久化到磁盘。但是,如果机器故障了或磁盘坏了,数据就不就全没了吗?这种情况应该怎么办呢?别担心,考虑主从模式。 主从模式 给主节点 Master 配置一个从节点 …

【T20天正电气V10.0软件下载与安装教程】

1、安装包 扫描下方二维码关注「软知社」,后台回复【024】三位数字即可免费获取分享链接,无广告拒绝套路; 2、安装教程双击T20天正电气V10.0安装包,弹窗安装对话框选择我接收,点击下一步选择安装位置,点击下一步点击下一步等待安装进度完成安装完成,点击完成按钮点击下…

windows底层激活破解一步到位,TSforge也太暴力了!

windows底层激活破解一步到位,TSforge也太暴力了! windows底层激活破解一步到位,TSforge也太暴力了! 微软系统一直是需要收费的,也是电脑用户们经常遇到的问题,市面上也有很多工具, 但是今天的工具是最新的且**呼声最高、最彻底的**,需要的话赶紧保存下来,实际使用只需…

No.23 CSS--定位

一、定义position属性指定了元素的定位类型。其中,绝对定位和固定定位会脱离文档流. 设置定位之后:可以使用四个方向值进行调整位置:Ieft、top、right、bottom.二、相对定位<head><meta charset="UTF-8"><meta name="viewport" content=&q…