DS 乱做

CF1422F Boring Queries

给定一个长度为 \(n\) 的序列 \(a\) 以及 \(q\) 次询问。

每次询问包含 \(2\) 个整数 \(l,r\) ,你需要求出区间 \([l,r]\) 的最小公倍数对 \(10^9 + 7\) 取模的结果。

\(1\leq n,q\leq 10^5,1 \leq a_i\leq 2\cdot 10^5,1\leq x,y \leq 10^5\)

这题有两个做法,首先讲 polylog 的,这基本上算一个套路了。

考虑最小公倍数直接求一定是困难的,我们套路地把这个东西放到质数幂上讨论。

因为质数幂需要取 \(\max\),一般直接维护是困难的,考虑如果离线,我们可以直接扫描线。如何维护该右端点的信息呢?我们发现可以记录上一个 \(p^k\) 出现的位置,然后在上一个位置乘上 \(p^{-1}\),因为这里我们已经贡献了 \(p\) 这个因子了。这样我们用一个主席树预处理就行了。时间复杂度 2log。

这题还有一个根号分治做法,考虑一个经典的事情,就是有用的质因子级别只有 \(O(\sqrt V)\) 的,因为大于这个值的质因子最多只有一个,这道题中可以直接单独用一个主席树维护。剩下的所有质数就用一个取 \(\max\) 的线段树维护即可。时间复杂度为 \(O(n\log n\log V+q\sqrt V)\)。后面除以 \(\ln\) 和乘上一个 \(\log\) 抵消了。当然你也可以 ST 表。

CF811E Vladik and Entertaining Flags

在一个 \(n*m\) 的网格上每个格子都有颜色,\(q\) 次询问,每次询问只保留 \(l\)\(r\) 列时有多少个四连通的颜色块。两个格子同色但不连通算在不同的颜色块内。

\(1\leq n\leq 10,1\leq m,q\leq 10^5\)

先讲个笑话,这个题 EI 的 \(O(nm+q)\) 没跑过另外一个人的小常数 \(O(nm\alpha(m)+qn)\),获得 CF 上 rk2 好成绩。

这个题 4 个复杂度,这里不讲 \(O(nm+q)\),因为过于复杂。

首先是最容易的 \(O(nm\alpha(n)+qn\log m\alpha(n))\)

直接用线段树维护,考虑怎么合并两个区间,直接记录两端并查集即可。合并和撤销就只撤销涉及到的点的 \(fa\) 即可。这样我们能知道合并在一起的连通块有多少个,就可以做一个减法得到这个区间的连通块个数。我的实现跑了 1100ms+,非常慢。

然后就是一个靠结论比较容易想到的 \(O((nm+q)\log n)\)

首先有平面图欧拉公式

\[V-E+F-1=C \]

其中 \(V\) 是点数,\(E\) 是边数,\(F\) 是被分割出来多少个不相连的区域数,\(C\) 是连通块个数。我们把颜色相同的格子连接起来,问题就变成了求 \(C\)。而 \(V,E\) 是容易处理的,一个直接算,一个前缀和。现在问题变到了如何求 \(F\) 上。

考虑 BFS 找到所有面的最左侧和最右侧需要的格子,现在就变成了有多少 \((l,r)\) 满足 \(L\leq l\leq r\leq R\),其中 \(L,R\) 为询问的区间,这就是一个二维偏序,离线树状数组即可。我的实现跑了 296ms,在 CF 上跑到了第一页。

这时候我打开了第一的程序,然后发现其实我们大可不用这样二维偏序。因为这个题 \(n\leq 10\),我们可以得到一个理论 \(O(nm+qn)\) 的做法,把上一个做法的 \(\log\) 平衡掉了。第一使用了并查集,而我使用的是 DFS,其实差不多,我 DFS 也带一个 \(4\) 倍常数。

考虑对于一列,最多有 \(2n\) 个区域(其中如果每个区域不记左端点,那么只有至多 \(n\) 个区域)穿过它,所以我们大可以统计右端点在这里的区域个数,然后对其做一个前缀和。这样我们多算的就是穿过了 \(l-1\)\(l\) 的区域,我们可以直接对于每个区域都把自己 push 到每一列的桶里。易得桶的大小 \(\leq 2n\)(或 \(n\)),暴力枚举 \(l\) 处的桶减去多余贡献就行了。但是实测我跑得巨慢,跑了 421ms/tuu。经过一堆卡常之后最快也只有 296ms,真傻比。

CF1946F Nobody is needed

一个长度为 \(n\) 的排列 \(a_{1...n}\)。有 \(q\) 次询问,每次给出 \(l,r\),求有多少个子序列 \(i_{1...k}\) 满足:

  • \(i_1\ge l,\space i_k\le r\)

  • \(\forall j\in [1,k-1],a_{i_j}|a_{i_{j+1}}\)

多测,\(T\) 组数据。

\(\sum n,\sum q\le 10^6\)

duel 的时候没做出来。

考虑扫描线 DP。设 \(f_i\)\(i\) 开始的合法子序列个数。显然加入一个数只会对在前面的其因数产生影响。那么一种想法就是把前面的其因数拉出来重新 DP 得到各处的贡献。

不过有一个简易的想法是,这个等同于可以在每个其因数开始的部分子序列在后面接上一个该数,考虑对于每一个位置计算从前面的因数到这个数的合法子序列个数,这样转移的时候只需要枚举 \(k|j|i\),然后把所有 \(k\to j\) 的贡献累加到 \(k\to i\) 上面。使用树状数组维护 \(f\) 的变化,这样做是 \(O(n\log^2 n+q\log n)\) 的,非常好写。但是不知道为什么跑得很慢,就算把 vector 换成指针。

CF992E Nastya and King-Shamans

给定一个序列 \(a_i\) ,记其前缀和序列为 \(s_i\) ,有 \(q\) 个询问,每次单点修改,询问是否存在一个 \(i\) 满足 \(a_i=s_{i-1}\) ,有多解输出任意一个,无解输出 \(-1\)

\(1\leq n,q\leq 2\times 10^5\)

这个题有好多好多做法。

首先考虑直接维护 \(s_i-2a_i\),不难发现这个东西为 \(0\) 的时候才有贡献。可以直接分块哈希表维护。复杂度单 sqrt。

然后考虑有贡献的时候是 \(s_i=2a_i\),这个时候 \(s_{i-1}\to s_i\) 的过程翻倍了,所以每次线段树查询 \(s_i-2a_i\geq0\) 的位置就行了,最多有 \(O(\log V)\) 次二分,所以时间复杂度是 \(O(n\log n\log V)\) 的。

然后就是高级 1log 做法。考虑对 \(a_i\) 倍增值域分块。然后以 \(2\) 为底数的话,只有可能是每一层的前两个点可能成为答案,修改的时候更新修改到的层的点和答案,然后遍历所有可能成为答案的点更新答案。查询的时候直接查现成的 \(s_i\) 即可。使用 BIT 和 set 维护,时间复杂度 1log。

但是经典老番之 1log 跑不过 2log。

CF986E Prince's Problem

给定你一棵树,有点权 \(val_i\le 10^7\)。现在有 \(m\) 组询问给定参数 \(x,y,w\) 问你对于 \(x\to y\) 的路径经过的点集 \(P\),问你这个东西:

\[\prod_{u \in P} {\mathrm{gcd}(w,val_u)} \mod 1000000007 \]

$ 1 \le n \le 10^{5} , 1 \le a_{v} \le 10^{7} $。

算是,经典老番了吧。

这个题不要想复杂就行了。首先把问题差分掉变成到根链问题。然后离线下来准备 DFS 一遍解决问题。

然后加入一个数就是在其所有 \(p^k\) 的因数的桶乘上一个 \(p\),然后询问就是遍历所有的 \(p^k\) 桶乘起来。

然后就做完了。不想要 2log 的话可以顺便去维护一个全是逆元乘起来的桶。

CF217E Alien DNA

好啦,来做做清新一点的题吧。

给出一串字符串,有 \(n\) 个操作,将区间 \([l,r]\) 的字符中编号为偶数的写下,再把奇数的写在后面,然后把它们插入 \(r\)\(r+1\) 之间,问最后字符串的前 \(k\) 位。

$ 1<=k<=3·10^{6} ,0\leq n\leq 5000$。

省流:复杂度是 \(O(n\log k+k)\)

首先遇到这种最后问前 \(k\) 位,然后操作有可能使得字符串有很多位的题,常见的做法就是倒序处理所有操作然后用并查集维护每一位是从哪里复制来的。

那么倒序处理,用并查集维护每个字符由什么而来。考虑使用链表维护每个点下一个没有确定从何而来的字符,也就是目前状态下的下一个字符,通过一次线段树二分得到 \(l,r\) 两端的字符位置,然后一次区间覆盖 \(0\) 把修改的区间设置为已经修改。

显然,如果视并查集复杂度为 \(O(1)\),那么复杂度就是省流的那样。

当然你其实不用并查集维护每个字符是怎么来的,但是链表维护的东西需要并查集辅助维护。

P8922 [MdOI R5] Squares

给定平面上的 \(n\) 个点,定义平面上的一个区域是好的当且仅当它是一个边与坐标轴平行的正方形并且不存在任何一个给定的点被它严格包含。再给定 \(m\) 次询问,每次给出一个点 \((x,y)\),求出严格包含 \((x,y)\) 的最大的好区域的边长。如果可以无限大则输出 \(-1\)

\(A\) 被区域 \(B\) 严格包含当且仅当 \(A\)\(B\) 的内部且不在边界上。

为了减少奇奇怪怪的细节,我们保证所有的 \(n+m\) 个点都满足横坐标互不相同,纵坐标互不相同。

\(1\le n,m\le 3\times 10^5\)\(0\le x,y\le 10^8\)

实现比较勾矢的题,常数大细节多。

考虑答案可能出现在哪些矩阵。因为横纵坐标互不相同,画图可以发现成为答案的矩阵至少会被 \(3\) 个维度限制。具体而言我们可以枚举三个维度,表示被这三个维度限制的正方形贡献了哪些点。这样有用矩阵个数就是 \(O(n)\) 的。

以左右下为例。实际上我们只需要枚举左右下和左右上就能搞定所有矩形,手玩出来可以知道。

枚举点当下的限制。然后在主席树上二分出最远的可以被贡献的坐标。然后把一个矩形的答案均设置为可以被贡献的坐标到原来坐标的距离。

注意到现在你已经可以扫描线 + 线段树上套 set 直接解决。但是这个 2log 常数极大,应该是无法通过的。(事实上 1log 都跑得非常非常慢了)

考虑利用一些限制降低复杂度。注意到 2log 瓶颈在 set,我们尝试将 set 替换成另外一个利用一些性质的数据结构。

注意到,答案的大小和存活时间是一样的,这里我们就可以把 set 换成单调队列一样的结构就行了,注意对同一位置的答案排一个序再加入线段树,否则可能因为加入顺序原因使得其不优。时间复杂度为巨大常数 1log。

CF1320D Reachable Strings

给定一个 \(01\) 串。每次询问两个等长的子串,询问是否可以从一个经过数次变换变成另一个。变换操作的定义是每次选定一个包含 \(110\) 或者 \(011\) 的子段,让 \(110 \to 011\) 或者 \(011 \to 110\)

\(n,q \leq 2 \times 10^5\)

好像是典题,但是最近看到的时候居然不会。Ad-hoc 能力急需提高。

首先注意到操作的时候所有元素的奇偶性不会变,进一步考虑,奇偶性不同的 \(0\) 不会互相跨越,所以我们可以直接维护奇偶性相对顺序的哈希,可以简单做到 1log。

posted @ 2024-09-23 22:51  xingyu_xuan  阅读(20)  评论(0编辑  收藏  举报