深入浅出程序设计竞赛(进阶篇)进阶数据结构
第五章 二叉堆
P2168 [NOI2015] 荷马史诗
P2827 [NOIP2016 提高组] 蚯蚓
找最长的蚯蚓只需要直到相对大小,其余蚯蚓长度 \(+q\) 等价于新产生的两条蚯蚓长度 \(-q\)
新产生的第一/二条蚯蚓长度分别单调,可以用队列代替堆
时间复杂度 \(O(n\log n+m)\)
P1801 黑匣子
对顶堆
P1631 序列合并
\(a,b\) 不降所以 \(a[i]+b[j]\) 一定比 \(a[i+1]+b[j],a[i]+b[j+1]\) 优
用堆维护可能成为答案的数对,取出 \((i,j)\) 后放入 \((i+1,j),(i,j+1)\)
P4053 [JSOI2007] 建筑抢修
第六章 线段树
P1438 无聊的数列
区间加等差数列
懒标记记录(首项,公差),下传时可以根据左子区间长度算出右子区间的首项,合并时首项、公差对应相加即可
P3373 【模板】线段树 2
有乘、加两个标记,记作 \((k,b)\)。比较自然的想法是让值为 \(ka+b\),\(\times x\) 后 \((ka+b)x=kxa+bx\),\(+x\) 后 \((ka+b)+x=ka+(b+x)\),仍然可以用 \((k,b)\) 表示
\(ka+b\) 经过 \((k',b')\) 作用时需要考虑下传顺序。注意到下传乘标记时加标记也乘了,所以应该先乘后加得到 \((ka+b)k'+b'\)
P4513 小白逛公园
区间最大子段和
维护区间最大子段和、最大前缀和、最大后缀和、区间和
P4145 上帝造题的七分钟 2 / 花神游历各国
\(10^{12}\) 开方下取整 \(6\) 次就变成 \(1\) 了,之后的开方都没有意义
其实不需要线段树,并查集 + BIT 即可
第七章 树状数组与字典树
lowbit(x) = x&-x:\(-x\) 的补码是 \(x\) 按位取反再 \(+1\),那么 \(x\) 末尾连续的 \(0\) 取反 \(+1\) 后恰好进位到 lowbit(x)
如果结点 \(j\) 包含位置 \(i\) 的信息,那么:
- \(j\ge i\)
- \(\text{lowbit}(j)\ge\text{lowbit}(i)\)(\(j=i\) 时取等):考虑 \([j-\text{lowbit}(j)+1,j]\) 中的所有数
- 这些 \(j\) 的 lowbit 互不相等:lowbit 相等的结点覆盖的区间无交
P5283 [十二省联考 2019] 异或粽子
\(n\) 个数。给定 \(i\),求 \(a[i]\oplus a[j]\) 的第 \(k\) 大值
trie 上维护每个子树的数字数量,查询类似线段树二分
P2161 [SHOI2009] 会场预约
P3586 [POI2015] LOG
先让 \(c\) 减掉 \(\ge s\) 的 \(a[i]\) 个数,之后只考虑 \(<s\) 的 \(a[i]\)
结论:只要 \(\sum a[i]\ge cs\) 就可行
证明:考虑构造 \(s\) 行 \(c\) 列的表格,每行的 \(c\) 个数表示要 \(-1\) 的下标,从上到下、从左到右填表即可。\(\sum a[i]\ge cs\) 保证了能填满,\(a[i]<s\) 保证了一行不会有两个相同数
P4592 [TJOI2018] 异或
DFS 序上的可持久化 01trie 实现子树询问
根链上的可持久化 01trie 配合树上差分实现链询问
第八章 线段树的进阶用法
P4587 [FJOI2016] 神秘数
对于给定可重集,从小到大依次考虑数 \(x\):设 \(r\) 是当前最小的不能被表示的数,若 \(x\le r\),那么 \(r\leftarrow r+x\),否则答案就是 \(r\)
据此得出做法:设 \(r'\) 为上次最小的不能被表示的数,\((r',r]\) 中的数都可以累加进 \(r\) 中,没有数可以累加则结束。每次累加的数 \(>r'\),最多累加 \(\log a\) 次
P3293 [SCOI2016] 美味
求 \(\max_{i=l}^{r}\{b\oplus a[i]+x\}\)
仍然是从高到低逐位贪心。设 \(b\) 的第 \(i\) 位为 \(1\),当前确定的答案为 \(b\oplus c\),若 \([c-x,c-x+2^{i}-1]\) 中有数那么不操作,否则令 \(c\leftarrow c+2^{i}\)
时间复杂度 \(O(m\log a\log n)\)
CF960F Pathwalks
有向图上边的 LIS
P2617 Dynamic Rankings
动态区间第 \(k\) 大
P2839 [国家集训队] middle
把 \(<mid\) 的数看作 \(-1\),\(\ge mid\) 的看作 \(1\),区间和 \(\ge0\) 代表中位数 \(\ge mid\)。可以通过对值域建主席树实现
二分答案 \(mid\)。求 \([a,b]\) 最大后缀和 \(+(b,c)\) 区间和 \(+[c,d]\) 最大前缀和即可判断

浙公网安备 33010602011771号