数据结构练习
T-Shirts
problem
有 \(n\) 种 T 恤,每种有价格 \(c_i\) 和品质 \(q_i\),有 \(m\) 个人要买 T 恤,第 \(i\) 个人有 \(b_i\) 元,每人每次都会买一件能买得起的 \(q_i\) 最大的 T 恤,如果有多个 \(q_i\) 最大的 T 恤,会从价格低的开始买。一个人只能买一种 T 恤一件,所有人之间都是独立的。
问最后每个人买了多少件 T 恤?
\(1\leq n,m\leq 2\times10^5\),\(1\leq c_i,q_i,b_i\leq 10^9\)
solution
平衡树维护每个人手中的钱,将T恤排序后依次考虑,修改树上的值并计算贡献。重复部分暴力插入,不重复部分打标记
Count on a tree
problem
给定 \(n\) 个结点的树,每个结点有一种颜色。\(m\) 次询问,每次询问给出 \(u\),\(v\),回答 \(u\),\(v\) 之间的路径上的结点的不同颜色数。颜色是不超过 \(2\times 10^9\) 的非负整数。
\(1\le n\le 4\times 10^4\),\(1\le m\le 10^5\)
solution
树上莫队+数颜色
强制在线?
树分块,\(\text{bitset}\) 维护路径颜色
Hello world!
problem
\(n\) 个点的树,每个节点有一个值 \(a_i\)。\(Q\) 次跳跃,每次跳跃会从一个点 \(s\) 出发跳到 \(t\)。每次跳跃会有一个步频 \(k\),表示如果从当前点到 \(t\) 的简单路径长度不超过 \(k\),那么就直接跳到 \(t\),否则沿着简单路径跳过恰好 \(k\) 条边。
每次跳跃会做下面两种操作之一
- 输出到达过的点的 \(a_i\) 之和
- 将到达过的点的 \(a_i\) 变为 \(\lfloor\sqrt{a_i}\rfloor\)
\(n\leq 5\times 10^4\),\(Q\leq 4\times 10^5\),\(1\leq a_i\leq 10^{13}\)
solution
每个数最多开根 \(\log\) 次
\(k\) 较小时建出虚树,树状数组 \(+\) 并查集维护
\(k\) 较大时暴力跳
小蓝的好友
problem
有一块 \(R\times C\) 的长方形土地。里面随机分布着 \(N\) 个资源点,第 \(i\) 个资源点的坐标为 \((x_i,y_i)\) ,求至少包含一个资源点的矩形区域的数量。
\(1\le R,C\le 4\times 10^4\),\(1\le N\le 10^5\)
,保证资源点的位置两两不同,且位置随机生成
solution
扫描线 \(+\) \(\text{treap}\) 维护笛卡尔树
大森林
problem
有 \(n\) 棵树,编号为 \(1\) 到 \(n\)。出始每棵树只有一个生长节点,有三种操作。
-
生长操作:将第 \(l\) 棵树到第 \(r\) 棵树的生长节点下面长出一个子节点,子节点的标号为上一个生长操作生成的点标号加 \(1\)(特殊的,第一个生长操作产生的子节点标号为 \(2\)), \(l\) 到 \(r\) 之间的树长出的节点标号都相同
-
修改操作:将第 \(l\) 棵树到第 \(r\) 棵树的生长节点改到标号为 \(x\) 的节点。对于 \(i\) 这棵树,如果标号 \(x\) 的点不在其中,那么这个操作对该树不产生影响
-
查询操作:询问第 \(x\) 棵树中节点 \(u\) 到节点 \(v\) 点的距离
\(N\leq 10^5\),\(M\leq 2\times 10^5\)
solution
发现询问可以在所有操作之后再做,将操作离线做扫描线
\(\text{LCT}\)维护一棵树
每次修改操作新建一个虚节点连接在上一个虚节点后,之后的生长操作的点连在最后一个虚节点上
扫描线进入一个修改区间时将对应的虚节点 \(\text{cut}\) 掉再 \(\text{link}\) 到修改到的节点上,离开时 \(\text{link}\) 回来
Escape Through Leaf
problem
有一颗 \(n\) 个节点的树。每个节点有两个权值,第 \(i\) 个节点的权值为 \(a_i\),\(b_i\)。
你可以从一个节点跳到它的子树内除自己外的任意一个节点上。从节点 \(x\) 跳到节点 \(y\) 的花费为 \(a_x\times b_y\)。跳跃多次走过一条路径的总费用为每次跳跃的费用之和。请分别计算出每个节点到达树的每个叶子节点的费用中的最小值。
\(2\leq n\leq10^5\),\(-10^5\leq a_i,b_i\leq 10^5\)
solution
写出dp式子,\(f[i]\) 表示 \(i\) 节点的答案
令 \(y=f[i]\),\(x=a[i]\),\(k=b[j]\),\(b=f[j]\) 可以将式子写为 \(y=kx+b\) 的形式,李超线段树 \(+\) \(\text{dsu on tree}\)
带插入区间K小值
problem
长为 \(n\) 的序列,单点插入、单点赋值、区间k小值查询
强制在线
\(n\leq 35000\),插入个数 \(\le 35000\),修改个数 \(\le 70000\),查询个数 \(\le 70000\),\(0 \le\) 每时每刻的权值 \(\le 70000\)。
solution
块状链表+值域分块
爷
problem
给你一个 \(n\) 个点的有根树,\(1\) 为根,带边权,有 \(m\) 次操作。
- 求 \(x\) 的子树中第 \(k\) 小的深度的值,如果子树中没有 \(k\) 个点则输出 \(-1\)
- 将 \(x\) 与 \(x\) 父亲的边权加上 \(k\)
保证每次操作 \(2\) 的 \(k\) 以及原树的边权小于等于一个数 \(\text{len}\)
\(n,m\leq 10^5\),\(\text{len}\leq 10\)
solution
对 \(\text{dfs}\) 序分块,二分答案 \(+\) 块内排序 \(+\) 块内二分可以做到 \(O(n\sqrt{n}\log^2n)\)
发现 \(\text{len}\) 只有 \(10\),于是可以维护每个块的极差,每隔一段时间将块重构,当极差大于某个设定值时将块分裂,这样就可以用桶排序 \(+\) 前缀和,也不需要块二分了,复杂度 \(O(n\sqrt{n}\log n)\)

浙公网安备 33010602011771号