继 算法竞赛进阶指南-学习笔记 之后的新内容。
将会比前面的简略许多,因为仅供个人使用。
0x41 并查集
P1955:
相等关系合并端点,不等关系若端点在同一集合则矛盾。注意离散化。实现。
UVA1316:
P1196:
P5937:
首先容易发现,若令 \(s_i\) 为 \(01\) 序列前缀和,则 \(s_r\) 与 \(s_{l-1}\) 奇偶性相同则有偶数个 \(1\),不同则有奇数个 \(1\)。
边带权做法:
令边权为 \(d_x\),若为 \(0\) 则 \(x\) 与 \(fa_x\) 奇偶性不同,反之则相同。
我们对于每个 \(x\),把从 \(x\) 到 \(fa_x\) 的 \(d\) 求 \(\operatorname{xor}\) 和即为 \(x\) 与 \(fa_x\) 的奇偶性关系。
对于询问 \((x,y)\),若它们在同一集合,则若 \(d_x \operatorname{xor} d_y=ans\)(\(ans\) 为答案)则不矛盾,否则矛盾;
若它们不在同一集合,则 \(x\) 与 \(y\) 的奇偶性关系 \(ans\) 即为 \(d_x \operatorname{xor} d_p \operatorname{xor} d_y\),进而可得两集合新边权 \(d_p=d_x \operatorname{xor} d_y \operatorname{xor} ans\)。
边带权做法的 实现。
扩展域做法:
将每个点 \(x\) 拆成 \(x_{odd}\) 与 \(x_{even}\),
若 \(ans=0\),则若 \(x_{odd}\) 与 \(x_{even}\) 在一个集合中则矛盾,否则合并 \(x_{odd},y_{odd}\)、\(x_{even},y_{even}\)。
否则反之同理可得。
扩展域做法的 实现。
还是注意离散化。
0x42 树状数组
Acwing241:
对于每个 \(y_i\),它对于 ^
的贡献即为 左边比 \(y_i\) 小的 \(y_j\) 个数 \(\times\) 右边比 \(y_i\) 小的 \(y_k\) 的个数。
同理亦可算出其对于 v
的贡献,分别用树状数组维护即可。
实现。
Acwing242:
差分即可。实现。
P3372:
仍然考虑差分。令差分数组为 \(b\)。
此时若对 \(a_{1 \sim x}\) 进行区间增加 \(v\),则其总增量即为
考虑拆这个式子:
于是我们维护两个数组 \(c_0,c_1\),分别保存 \(\sum_{i=1}^x b_i\) 与 \(\sum_{i=1}^x i \times b_i\)。
然后按照上式进行区间修改与查询即可。
实现。
Acwing244:
倒序确定每头牛,容易发现每头牛的身高 \(H_k= 1 \sim n\) 中第 \(A_k+1\) 小的不存在于 \(H_{k+1 \sim n}\) 的数。
于是我们用树状数组维护 \(01\) 序列 \(b\) 的前缀和,\(b\) 起初全为 \(1\)。
二分这个位置,通过 ask(mid)
即可查询前面有多少个 \(1\),若比 \(A_k\) 小则往大猜,否则往小猜。
二分做法的 实现。
当然用倍增也可以做,就是枚举 \(p\),以 \(2^p\) 为步长去凑即可。这个实现先咕着。
0x43 线段树
SP1716(Acwing245):
很基础的线段树,但是实现细节挺多。
令 \(sum\) 维护区间和,\(lmax\) 维护靠左端的最大子段和,\(rmax\) 维护靠右端的区间子段和,\(dat\) 维护区间子段和。
于是 pushup
时有:
(以下令 \(p\) 为父节点,\(ls,rs\) 为左、右子节点)
在 build
和 update
中如此传递信息即可。
在 ask
中,我们也是如此累计答案,但在 \(l > mid\) 与 \(r \le mid\) 的情况时(\([l,r]\) 为询问区间,\(mid\) 为当前区间中点),答案的 \(lmax\) 与 \(rmax\) 需要分别对于 \(\large{t_{rs_{lmax}}}\) 与 \(\large{t_{ls_{rmax}}}\) 取 \(\max\)。
实现。
Acwing246:
直接用线段树维护带修的区间 \(\gcd\) 是过不了的,
所以我们建立原数组 \(A\) 的差分数组 \(B\),
这样就把区间修改转为两次单点修改。
因为我们有:
(这玩意似乎可以用 \(\gcd(x,y)=\gcd(x,y-x)\)(更相减损术)运用数学归纳法证明,但是我先咕着)
所以可以运用线段树维护 \(B\) 的区间 \(\gcd\),
然后询问就等于求出 \(\gcd(a_l,\operatorname{ask}(1,l+1,r))\),
其中因为要求 \(a_l\),所以还得套个树状数组。
然后这题就做完了。实现。
P3372:
板子。实现。