Solution Set -「DS 专题」兔年的兔子写 DS 会有小常数吗?
大家好, 她是小梅香, 是雨兔最可爱的妹妹. (
仅有对 DS 的非平凡使用会打 tag, 如果仅仅拿线段树维护个区间加减区间和啥的就不打了.
\newcommand{\chr}[1]{\underline{\texttt{#1}}}
\]
Day 1
「Ynoi 2009」「洛谷 P6109」rprmq1 ^
- Link & Submission.
「Ynoi Easy Round 2021」「洛谷 P8512」TEST_152
Link & Submission.
「C.复杂度分析」
操作只有区间赋值? 立马向珂朵莉树的方向思考. 注意若模拟所有 \(n\) 次操作, 一共只有 \(\mathcal O(n)\) 次区间贡献变化, 而这些变化也仅仅是单纯的区间加减. 因此, 可以对询问的 \(r\) 扫描线, 用数据结构维护每个 \(l\) 对应的答案. 复杂度 \(\mathcal O((n+q)\log m)\).
「Ynoi 2005」「洛谷 P7907」rmscne
Link & Submission.
「C.性质/结论」
这题麻烦的地方在于, 最终的答案区间很可能有 \(l<l'\le r'<r\), 左右端点都会向内缩, 我们就没有办法固定一端做扫描线之类的工作. 这也提示我们, 应该先去思考关于合法区间的性质.
其实, "枚举端点" 是 "固定端点" 的有力方法. 对于询问 \([l,r]\), 设有最小的 \(p\), 使得 \([p,r]\) 合法. 我们在 \([l,p]\) 中枚举左端点 \(l'\), 找到此时使得 \([l',r']\) 关于 \([l',r]\) 合法的最大 \(r'\), 再求 \(r'-l'+1\) 的最大值就是答案.
通过等价转化, 我们使 \(r'\) 仅与左端点 \(l'\) 和固定端点 \(r\) 有关, 这时候就能对 \(r\) 扫描线了. 令 \(p_i\) 表示 \(l'=i\) 时最小的 \(r'\), 对于询问, 我们需要完成两个工作: 1) 求出 \(p\); 2) 求出 \([l,p]\) 中 \(p_i-i+1\) 的最大值. 对于前者, 维护方法很多, 但用 DSU 之类的小常数做法才不会被卡常. 对于后者, 可以用线段树简单维护. 于是我们得到了 \(\mathcal O((n+q)\log n)\) 的做法.
「Ynoi 2010」「洛谷 P6105」y-fast trie
Link & Submission.
「B.Tricks」「C.性质/结论」
对 \(i+j\ge C\) 的情况, 维护全局最大次大即可. 我们主要讨论 \(i+j<C\) 的情况. 设在某一时刻 \(i\) 的最优匹配数为 \(p(i)\), 显然仅有 \(p(p(i))=i\) 的 \(i+p(i)\) 可能贡献答案 (trick), 我们需要时刻维护这一双向最优匹配关系.
这里以插入的讨论为例. 设当前集合还未插入, 即将插入 \(x\). 找到 \(y=p(x),z=p(y),w=p(z)\). 若 \(y\) 存在且(\(z\) 不存在或者 \(z<x\)), 则 \((x,y)\) 为新增双向对, 在此条件下此, 若 \(z\) 存在且 \(w=y\), 则 \((y,z)\) 为被 \((x,y)\) 顶替, 将被删除的双向对. 用可删堆维护双向对贡献, std::map
或者 std::multiset
维护集合以计算 \(p\) (推荐前者, 因为 std::multiset::count
的复杂度不正确), 可以做到 \(\mathcal O(n\log n)\).
「北大集训 2021」「LOJ #3673」简单数据结构
Link & Submission.
「A.分治-整体二分」「A.分治-数据结构上二分」「A.数据结构-李超树」「A.数据结构-线段树」「C.细节」
(注意代码 L112 amx[u] += k * rig[u]
逻辑有误, rig[u]
应改为区间内 activated 的最右位置而非区间右端点. 应该能卡, 不知道为什么能过.)
自然地发现, 若所有 \(a_i\) 初始为 \(0\), 则 \(\{a_n\}\) 永远单调, 操作 1 的效果变为后缀赋值, 这时结合线段树二分, 我们可以用线段树方便地维护操作.
受此启发, 我们尝试把原问题化归到这种情况. 此时, 我们需要求出每个 \(a_i\) 第一次被取 \(\min\) 的时间 \(t_i\): \(t_i\) 之前, \(a_i\) 不会被取 \(\min\), 维护很方便; \(t_i\) 之后, 所有同 \(a_i\) 一样被取过 \(\min\) 的 \(a_j\) 构成的子序列是单调的, 可以用上面的方法维护. 这部分可以做到 \(\mathcal O(q\log n)\), 只是实现较为恶心.
最后的问题, 如何求 \(t_i\)? 注意每个操作 1 前操作 2 的次数一定, 因此对于 \(a_i\) 若其一直未被取 \(\min\), 到第 \(j\) 个操作 1 时的值可以写作 \(k_j\times i+a_i\). 整体二分, 李超树插入这些直线以划分左右子问题即可. 这部分可以做到 \(\mathcal O(n\log^2n)\).
Day 2
「北大集训 2021」「LOJ #3676」小明的树
Link & Submission.
「A.数据结构-线段树」「B.Tricks」
经典老番:
- 美丽 \(\Leftrightarrow\) 黑点构成连通块 \(\Leftrightarrow\) 第 \(i\) 次操作后, \(n-1-i=c\), \(c\) 为黑-黑边数.
- 美丽时, 白点连通块数 \(=d\), \(d\) 为黑-白边数.
- \(n-1-i\ge c\).
线段树在时间轴上维护区间最小值及其对应黑-白贡献即可. \(\mathcal O((n+m)\log n)\).
「BalkanOI 2018」「洛谷 P4786」Election ^
- Link & Submission.
「HNOI 2011」「洛谷 P3215」括号修复
Link & Submission.
「A.数据结构-平衡树」「C.性质/结论」「C.细节」
对括号串的处理应该是得心应手了. 设 \(\chr (,\chr )\) 分别对应 \(1,-1\), 前缀和最小值为 \(p\le 0\), 后缀和最大值为 \(q\ge 0\), 不难证明答案为 \(\lceil-p/2\rceil+\lceil q/2\rceil\). 用一大坨平衡树维护这两个值即可. 复杂度 \(\mathcal O((n+q)\log n)\).
「HNOI 2015」「洛谷 P3242」接水果
Link & Submission.
「A.分治-整体二分」「B.DFN」
整体二分答案, 盘子对水果的贡献形式是 DFN 上的二维数点. \(\mathcal O((n+q)\log^2n)\).
「Ynoi 2010」「洛谷 P6018」Fusion tree
Link & Submission.
「A.数据结构-Trie」
波奇酱剖分 定根, 每个点维护孩子们的点权集合. 难点在于对集合的整体 \(+1\).
分析发现, \(+1\) 进位的数一定是奇数, 即最低 bit 为 \(1\), 进位等价于对从次低 bit 开始的数 \(+1\), 这是一个子问题. 以 Trie 树的视角, 对 \(u\) 子树 \(+1\) 相当于交换左右子树, 然后递归向左子树. 这样就能维护了. 最终复杂度 \(\mathcal O((n+q)\log V)\).
「OurOJ #6861」party
简要题意
给定一棵含 $n$ 个点的有根树, 点有颜色. 处理 $q$ 次询问, 每次给出 $c$ 个点, 每个点在自己走向 LCA 的路径上选择相同数量的若干颜色, 颜色不能与其他点选的颜色有交. 回答最多选出的颜色总数.
$n\le3\times10^5$, 颜色种类 $m\le10^3$, $q\le5\times10^4$, $c\le5$.
- 「B.复杂度平衡」「C.性质/结论」
我似乎写了个怪做法.
"选出颜色数量相同" "颜色不交", 若已知每个点选 \(k\) 个颜色, 则将每个点复制 \(k\) 份, 每个复制点连向原点能选择的颜色, 用 Hall 定理检查合法性. 反过来, 枚举 Hall 定理检查的集合 \(S\), 设 \(S\) 中的点总共能选择 \(c_S\) 种颜色, 则有限制 \(k\le c_S/|S|\). 只需要求出所有 \(c_S\), 取最小值即为答案.
注意 \(m\times q\times c\) 勉强能被接受, 可以直接枚举颜色, 用 \(\mathcal O(\sqrt n)\) 区间加 \(\mathcal O(1)\) 查单点的序列维护手法维护每个点祖先内的当前颜色数量, 再枚举询问和询问中的结点, 求出可以选择当前颜色的结点集合 \(S\) 暂存入 \(c_S\). 此后回答询问时, 先用 FMT 之类的东西还原出 \(c_S\), 再求答案即可.
复杂度有三部分, 大概是 \(\mathcal O(n\sqrt n+mqc+qc2^c)\), 不过规避了 std::bitset
. (
Day 3
「Ynoi Easy Round 2020」「洛谷 P8264」TEST_100
- Link & Submission.
- 「A.分块」「A.数据结构-并查集」「B.Tricks」
先给这个 "线性变换" 一个比较形象的解释: 让 \(x\) 向 \(0\) 位置走 \(a_i\) 步. 因此可以发现,一个区间内的数分别经过同样的若干变换后的结果仍然构成一段区间.
利用这个结论, 我们可以考虑分块. 对于整块 \([l,r]\), 维护映射关系 \(\varphi_{[l,r]}:[1,n]\to[0,n]\), 用以描述 \([1,n]\) 从左侧输入 \([l,r]\) 后, 在 \(r\) 输出的结果. 变换过程是对区间的位移和折叠, 这是一个经典 trick, 用并查集维护, 由于必要的并查集找根操作是在并查集定形后统一进行的, 所以并查集的 \(\alpha(n)\) 也是可以规避的. 最终复杂度 \(\mathcal O((n+m)\sqrt n)\).
「POI 2015」「洛谷 P3591」ODW
- Link & Submission.
- 「B.复杂度平衡」
维护个 \(\mathcal O(1)\) \(k\) 级祖先, 步长 \(\mathcal O(\sqrt n)\) 以内的维护祖先上与当前点深度关于步长同余的结点权值和 \(\mathcal O(1)\) 查询; 步长 \(\mathcal O(\sqrt n)\) 以上的暴力跳. 复杂度 \(\mathcal O(n\sqrt n)\).
「Ynoi 2014」「洛谷 P5063」置身天上之森
- Link & Submission.
- 「A.分块」「C.性质/结论」
注意到线段树区间长度仅有 \(\mathcal O(\log n)\) 种, 当区间长度想同时, 批量修改才容易完成, 因此我们可以直接对这 \(\mathcal O(\log n)\) 种长度的区间分别求解.
对于固定的区间长度, 我们需要处理区间加, 区间求 rank. 分块后维护块内排名即可.
平衡块长得到理论最优复杂度 \(\mathcal O(m\sqrt{n\log n})\), 注意不要在不必要的地方引入瓶颈 (比如, 一些地方可以归并排序).
「Ynoi 2018」「洛谷 P5397」天降之物
Link & Submission.
「B.复杂度平衡」「B.Tricks」
维护颜色, 很自然地想到根号平衡. 这里算是有个没见过的 trick: 设阈值为 \(B\), 将集合 \(S\) 表示为 \(P\cup Q\), 其中 \(|Q|<B\). 小集合之间与大集合之间的合并都可以暴力, 小集合合并入大集合时, 先加入 \(Q\), 若 \(|Q|\ge B\) 再重构 \(S\). 计算贡献时, \(Q\) 仍然可以作为一个小集合算答案, 这样我们的复杂度得以保证. 复杂度 \(\mathcal O(m\sqrt n)\), 实现时只需要记录 \(Q\) 和大集合与其他集合间的答案.
「Ynoi 2018」「洛谷 P4119」未来日记
- Link & Submission.
- 「A.分块」「B.复杂度平衡」「C.细节」
向身边的 Ynoi 大师询问得知这题卡 \(\log\), 那么第一个思考的点就是如何再不引入 \(\log\) 的情况下求第 \(k\) 小? — 像主席树的静态第 \(k\) 小一样, 若我们得到了左右端点的前缀和序列, 且知道每 \(\sqrt n\) 个数的和, 我们就可以 \(\mathcal O(\sqrt n)\) 地求出第 \(k\) 小.
问题转化到维护这一前缀和序列. 显然不可能对每个端点维护, 我们还需要分块, 仅维护整块右端点处的前缀和序列. 整块用并查集维护颜色转换 (比较复杂, 注意空间消耗), 散块暴力, 可以做到 \(\mathcal O((n+m)\sqrt n)\).
卡了 \(17\) 发常, 注意规避瓶颈处的 random acess. 卡常的时候可以先注释代码找到实际瓶颈再针对性卡常.
Day 4
「Ynoi 2017」「洛谷 P5356」由乃打扑克
- Link & Submission.
- 「A.分块」
分块, 修改时整块标记散块归并, 查询二分答案, 再枚举每个块二分数量…
啊你说这个东西是人人都会的暴力怎么可能有分? 设块长为 \(B\), 复杂度 \(\mathcal O(B+n/B+\log V\cdot n/B\cdot\log n)\), 取 \(B=\sqrt{n\log n\log V}\), 平衡出 \(\mathcal O(n\sqrt{n\log n\log V})\), 也就是 \(n\sqrt n\) 带一个 \(\log\), 可以过.
注意二分时 \(l+r\) 可能超过 \(2^{31}\), 会被 hack.
「洛谷 P2137」Gty 的妹子树
- Link & Submission.
- 「A.分块」
操作分块, 对于原有结点, DFN 序列上值域线段树处理查询; 对于新增结点, 通过维护最接近的原有结点的 DFN 来判断子树关系并处理查询. 理论最优复杂度 \(\mathcal O(m\sqrt{n\log n})\).
「洛谷 P3863」序列
- Link & Submission.
- 「A.分块」
在原序列上扫描线, 分块维护时间轴, 把由乃打扑克的代码贺过来改改就完了. 理论最优复杂度 \(\mathcal O(q\sqrt{q\log q})\).
「Ynoi 2018」「洛谷 P4117」五彩斑斓的世界 ^
- Link & Submission.
「Ynoi 2019」「洛谷 P6578」魔法少女网站
- Link & Submission.
- 「A.分块」「B.离线」
我们几乎无法避免 \(\mathcal O(1)\) 处理块内 lower-bound, 但空间不允许…
一个简单的处理方法是按块离线, 每次处理一块区间的修改和询问. 再用一个分块动态维护 \([1,n]\) 内的数在当前块的排名, 同时处理块内答案, 为了处理块间贡献, 还要处理类似第一次最后一次出现位置的信息. 维护一大堆东西, \(\mathcal O(m\sqrt n)\).
Solution Set -「DS 专题」兔年的兔子写 DS 会有小常数吗?的更多相关文章
- Diary / Solution Set -「WC 2022」线上冬眠做噩梦
大概只有比较有意思又不过分超出能力范围的题叭. 可是兔子的"能力范围" \(=\varnothing\) qwq. 「CF 1267G」Game Relics 任意一个 ...
- Solution Set -「ARC 107」
「ARC 107A」Simple Math Link. 答案为: \[\frac{a(a+1)\cdot b(b+1)\cdot c(c+1)}{8} \] 「ARC 107B」Quadrup ...
- ☕【Java技术指南】「OpenJDK专题」想不想编译属于你自己的JDK呢?(Windows10环境)
Win10下编译OpenJDK8 编译环境 Windows10专业版64位: 编译前准备 Tip: 以下软件的安装和解压目录尽量不要包含中文或空格,不然可能会出现问题 安装 Visual Studio ...
- 🏆【Java技术专区】「编译器专题」重塑认识Java编译器的执行过程(消除数组边界检查+公共子表达式)!
前提概要 Java的class字节码并不是机器语言,要想让机器能够执行,还需要把字节码翻译成机器指令.这个过程是Java虚拟机做的,这个过程也叫编译.是更深层次的编译. 在编译原理中,把源代码翻译成机 ...
- ☕【Java技术指南】「编译器专题」重塑认识Java编译器的执行过程(常量优化机制)!
问题概括 静态常量可以再编译器确定字面量,但常量并不一定在编译期就确定了, 也可以在运行时确定,所以Java针对某些情况制定了常量优化机制. 常量优化机制 给一个变量赋值,如果等于号的右边是常量的表达 ...
- ☕【Java技术指南】「TestNG专题」单元测试框架之TestNG使用教程指南(上)
TestNG介绍 TestNG是Java中的一个测试框架, 类似于JUnit 和NUnit, 功能都差不多, 只是功能更加强大,使用也更方便. 详细使用说明请参考官方链接:https://testng ...
- ☕【Java技术指南】「编译器专题」深入分析探究“静态编译器”(JAVA\IDEA\ECJ编译器)是否可以实现代码优化?
技术分析 大家都知道Eclipse已经实现了自己的编译器,命名为 Eclipse编译器for Java (ECJ). ECJ 是 Eclipse Compiler for Java 的缩写,是 Jav ...
- Solution Set -「ABC 217」
大家好屑兔子又来啦! [A - Lexicographic Order] 说个笑话,\(\color{black}{\text{W}}\color{red}{\text{alkingDead} ...
- 【Java技术专题】「原理专题」深入分析Java中finalize方法的作用和底层原理
finalize方法是什么 finalize方法是Object的protected方法,Object的子类们可以覆盖该方法以实现资源清理工作,GC在首次回收对象之前调用该方法. finalize方法与 ...
- Note -「Lagrange 插值」学习笔记
目录 问题引入 思考 Lagrange 插值法 插值过程 代码实现 实际应用 「洛谷 P4781」「模板」拉格朗日插值 「洛谷 P4463」calc 题意简述 数据规模 Solution Step 1 ...
随机推荐
- FFmpeg 视频转 GIF
Filtergraph 在 ffmpeg 命令中,可以使用 -filter.-vf.-af 或 -filter_complex 选项指定 filter graph Filtergraph 由 filt ...
- spring boot中使用quratz实现定时。 使用task直接调用的实现方法
1.定义工作类 2.创建配置类,将工作对象绑定到工作明细,然后创建触发器 与工作明细进行绑定 二.使用task实现定时任务 1.启动类上开启定时功能 2.在需要定时的任务上增加Schedule注解,并 ...
- 5.4 Linux Vim基本操作
<Vim三种工作模式>一节给大家详细介绍了 Vim 的 3 种工作模式,本节来学习如何使用 Vim 编辑文件. 首先学习如何使用 Vim 打开文件. Vim 打开文件 使用 Vim 打开文 ...
- 推荐一个跨平台支持Word, Excel, CSV, Email等30多种格式的操作库
更多开源项目请查看:一个专注推荐优秀.Net开源项目的榜单 在我们日常项目开发中,经常需要解析操作文档,比如Office文档.Email文件.PDF.Xml.图片.Mp3等音频文件,操作Office. ...
- 鸿蒙NEXT开发案例:年龄计算
[引言] 本案例的目标是开发一款年龄计算器应用,该应用能够根据用户输入的出生日期,计算出用户的实际年龄.虚岁.星座.生肖等信息.同时,应用还将提供距离下次公历和农历生日的天数及星期等信息.为了实现 ...
- Educational Codeforces Round 151 (Rated for Div
C. Strong Password 给定一个字符串\(s\),一个密码的长度\(m\),下界字符串\(l\)和上界字符串\(r\),上下界字符串长度均为\(m\),且字符只在0~9范围内,上界字符串 ...
- AmplifyImpostors源码阅读
首先看一下点击Bake按钮后的执行流程: 1.AmplifyImpostorInspector部分 首先点击按钮设置了bakeTexture = true if( GUILayout.Button( ...
- GUETSEC
1. GUETSEC栈溢出 可以看到它看起来好像有四个栈溢出,我们逐个点进去 __isoc99_scanf("%20s", v1):限制了读取20个字符串(但其实无法完全杜绝缓冲区 ...
- Caused by: org.gradle.api.internal.plugins.PluginApplicationException: Faile
解决方法: 1.新建一个安卓应用,复制下面路径红色框的代码 去替换 导入应用中的代码,就是修改gradle版本: 2.在导入的应用中如下路径添加信息 代码: android.overridePat ...
- HarmonyOS Next 入门实战 - 创建项目、主题适配
开发一个简单的demo,其中涉及一些鸿蒙应用开发的知识点,其中涉及导航框架,常用组件,列表懒加载,动画,深色模式适配,关系型数据库等内容,在实践中学习和熟悉鸿蒙应用开发. 首先下载并安装 ...