Loading

数据结构做题笔记

LG2827 [NOIP2016 提高组] 蚯蚓

用单调队列简单维护就可以做到 $O(m\log m) $,但 \(m\) 有点大,我们就需要考虑特殊性质。
注意到每次切割的蚯蚓长度一定小于前几次切割的长度(指的是没有每天增加 \(q\) 的情况下)。
这样考虑使用队列 \(q[3]\) 分别维护还没有切割的,切割后左边的,切割后右边的即可。
时间复杂度 \(O(m)\)
另外读入的数组并不是单调的,但是给出的样例却都是单调的。

LG5268 一个简单的询问

区间询问,\(10^5\) 级,想到莫队。
但每个询问拥有两个约束条件,不能直接处理。
\(p_{l,x}\) 表示 \(1\sim l\)\(x\) 的出现次数。

\[\begin{aligned}&\ \ \ \ \ \ get(l_1,r_1,x)\times get(l_2,r-2,x) \\ &=(p_{r_1,x}-p_{l1-1,x})\times(p_{r_2,x}-p_{l_2-1,x})\\ &=p_{r_1,x}\times p_{r_2,x}+p_{l_1-1,x}\times p_{l_2-1,x}-p_{l_2-1,x}\times p_{r_1,x}-p_{r_1,x}\times p_{l_2-1,x}\end{aligned} \]

\(q\) 个询问拆成 \(4q\) 个子问题,就可以使用莫队统一求解。

LG3045 Cow Coupons G

想到一个结论——

\(c\) 值前 \(k\) 小的奶牛一定会被购买。

考虑反证法。
如果 \(c\) 值前 \(k\) 小的奶牛为被购买,那么就一定可以将其中的奶牛代替现在使用优惠的奶牛,方案更优。
但是, \(c\) 值前 \(k\) 小的奶牛并不一定会使用优惠券。
假设已经购买的奶牛中使用优惠的一头奶牛为 \(x\) ,未使用优惠的奶牛为 \(y\),那么当且仅当 \(p_x-c_x<p_y-c_y\) 时,将 \(x\) 的优惠给 \(y\) 使用会使得整体方案更优。于是如果出现了上述情况, \(c\) 值前 \(k\) 小的奶牛可以考虑不使用优惠使得整体方案更优。
考虑先将 \(c\) 值前 \(k\) 小的奶牛加入购买方案,全部使用优惠券,再考虑其它的奶牛。
对于一头奶牛 \(i\) 有两种方案,一种是直接购买,花费 \(p_i\), ,另一种是取代奶牛 \(j\) 的优惠券,花费为 \(p_j-c_j+c_i\)
使用三个优先队列分别维护 \(p_i,c_i,p_j-c_j\) 的最小值。

LG3586 LOG

思考询问操作如何处理。
发现如果任何一个节点如果大于 \(s\) 的话,最多发挥 \(s\) 的价值。
因此我们只需要找到大于等于 \(s\) 的数的个数,还有小于 \(s\) 的价值的和就可以得出能否进行 \(s\) 次操作。
相当于需要一个支持找到数的排名,全局第 \(k\) 小,查询区间和还有单点修改的数据结构,用平衡树维护。

LG4514 上帝造题的七分钟

使用差分和前缀和进行维护数值。
设差分数组为 \(s_{a,b}\),每次区间修改就使 \(s_{a,b},s_{c+1,d+1}\) 加一,\(s_{c+1,b},s_{a,d+1}\) 减一,使用树状数组维护前缀和即可求出单点的数值。
现在问题转到区间的求和。

\[\begin{aligned}&\ \ \ \ \ Sum_{x,y}\\&=\Sigma_{i=1}^x\Sigma_{k=1}^i\Sigma_{j=1}^y\Sigma_{s=1}^ys_{k,s}\\&=\Sigma_{k=1}^x\Sigma_{s=1}^y(x-k+1)(y-s+1)s_{k,s}\\&=\Sigma_{k=1}^x\Sigma_{s=1}^y[(xy+x+y+1)s_{k,s}+(-x-1)ss_{k,s}+(-y-1)ks_{k,s}+kss_{k,s}]\end{aligned} \]

使用二维树状数组维护 \(s_{k,s},ss_{k,s},ks_{k,s},kss_{k,s}\)

LG3960 列队

容易想到将 \(n\times m\) 的矩阵分为 \(n+1\) 个数列用平衡树维护。
\(n\) 棵为 \(n\) 行的前 \(m-1\) 个元素。
最后一棵平衡树维护 第 \(m\) 列的 \(n\) 个元素。
注意到 \(n,m\leq3\times 10^5\),用平衡树直接维护空间显然会炸掉。
然而操作数 \(q\) 也是 \(10^5\) 量级,所以我们想到可以用一个节点维护一个区间范围内的数,当这个区间 \([l,r]\) 内的 \(x\) 位置的数需要删除的时候将这个区间删除,并插入 \([l,x-1]\)\([x+1,r]\) ,这样就可以减少空间复杂度。
注意到一个问题,我们需要一个关键字排序需要保证区间有序。分裂的区间是可以直接插入的,但是从第 \(m\) 列插入的数还需要保证有序。于是我们将从后面插入的数 加上 \(x\times nm\)\(x\) 随着插入逐渐增加,做好标记。读取的时候再减去就好了。

LG3302 森林

如果只有询问操作,就直接在树上构建主席树,在主席树上二分就可以了。
但是还有连边操作,考虑启发式合并,每次连边将节点数较小的树接到节点数较大的树上,暴力重构节点数较小的那部分的主席树即可。

LG3293 美味

看到异或值最大,想到类似于 01-trie 的做法。
询问区间信息,又是与权值有关,自然想到主席树。
从高到低枚举,设前面已经找到的最大的权值为 \(pre\)(还没有枚举到的数默认填 0)。
我们假设第 \(i\) 位需要 1,只要在主席树上查询 \([pre+2^{i-1},pre+2^i )\) 这个区间有没有数,没有的话这一位只能填 0。
需要 0 的情况也是一样。

LG3644 八邻旁之桥

\(k=1\), 中位数就是答案。
\(k \leq 2\),考虑可以将整个河岸分成两个部分,于是从前往后,从后往前分别跑一次求动态中位数。
用对顶堆,平衡树或者权值线段树都可以维护。

LG3380 二逼平衡树

树套树板子。
区间线段树套平衡树,相当于对每个线段树的节点都建立一棵平衡树,空间复杂度 \(O(nlogn)\)
查询区间排名就只需要在属于该区间的 \(O(logn)\) 个线段树节点中的平衡树分别查询。
查询区间第 \(k\) 小,在查询区间排名的基础上二分,时间复杂度 \(O(nlog^3n)\)
修改就在包含该节点的 \(O(logn)\) 个线段树节点的平衡树中分别修改。

LG2617 Dynamic Rankings

树状数组套权值线段树(其实上面那题也可以用的,不仅时间复杂度更优,而且好写)。
修改同一般的树状数组,只是每个节点要在主席树上修改。
查询将 \(O(logn)\) 个节点拿出来,在这几棵主席树上同时二分。

LG3332 K大数查询

其实一开始写的是区间线段树套权值线段树的,结果发现空间爆炸,只有 20 分。因为这题是区间加。
所以需要权值线段树套区间线段树,直接在权值线段树上二分。

LG3759 不勤劳的图书管理员

鉴于出题人语文可能不太好,需要翻译一下题面。
给定 \(a_i,v_i,求 \Sigma_i\Sigma_{j<i}[a_i<a_j](v_i+v_j)\),带修改(指两点交换)。
树状数组套权值线段树可以求出一个位置的数和其前缀的答案。
修改就在这个基础上做一些加加减减。

LG3242 接水果

树上的区间包含问题,考虑用 dfs 序转化。
\(L_x\) 表示 \(x\) 的 dfs 序,\(R_x\) 表示以 \(x\) 为根的子树内的 dfs 序的最大值,即 \(R_x=L_x+size_x-1\)
设水果为 \([x,y]\),那么盘子 \([u,v]\) 要想被水果包含,就有两种情况。
不妨设 \(depth_u<depth_v\)

  • \(lca_{u,v}=u\),设 \(z\)\(u\rightarrow v\) 上第一个节点。
    需要满足\(L_x\in[1,L_z-1]\cap [R_z+1,n],L_y\in[L_u,R_u]\)
  • \(lca_{u,v}\neq u\)
    需要满足 \(L_x\in[L_u,R_u],R_x\in[L_v,R_v]\)

不妨将这两个节点看作一个二维空间上的坐标,要求的区间信息则可以看成是一个矩形。按 \(x\) 坐标排序,类比扫描线的思路维护 \(y\) 轴上的信息。现在我们需要一个支持区间插入,查询单点第 \(k\) 小的数据结构,用权值线段树套区间线段树维护。

posted @ 2023-03-27 14:40  xkjie  阅读(25)  评论(0)    收藏  举报