Cry_For_theMoon  

1. count

感觉是一类组合计数的综合题。刚好可以完整梳理一下。

首先长度为 \(2n\) 的合法括号串计数是最经典的问题:合法性可以转成 \(+1/-1\) 的序列来判断,则合法等价于和为 \(0\) 且任意前缀和非负。

把过程看作是在网格图上游走,也就是 \((0,0)\rightarrow (n,n)\) 且不穿过 \(y=x\) 这条直线的方案数。

我们知道这个就是卡特兰数。

卡特兰数可以对应到括号上,然后再对应到树上:任意一个 \(n+1\) 个点的有根(无标号)树都和一个长度为 \(2n\) 的合法括号序列一一对应,考虑 dfs 的过程,当我们从一个点进入它的儿子的时候打入左括号,否则打入右括号。这样一棵树对应一个合法括号序列,反过来也容易发现一个括号序列唯一对应一棵树(这个括号串建树套路似乎还是典)。

而树可以对应到二叉树,具体地,\(n+1\) 个点的有根无标号树个数就是 \(n\) 个点的有根无标号二叉树个数。(如果只有一个儿子,左右是会区分的)。

考虑二叉树转普通树:初始有一个根 \(u\),然后选择根一直往左走到不能再走这条左链,\(u\) 连向这条链的所有点。然后考虑每个点的右儿子构建出来的若干个子树就连到这个点上。也容易发现转回去也是唯一的。

不过事实上,直接列出递推式计算也容易发现上面的这个事实。

回到本题:以 \((value,index)\) 二元组作为关键字建出大根的笛卡尔树,则两个序列相等等价于他们的笛卡尔树相同。

然而不是所有笛卡尔树都合法的:注意到若存在一个点,\(root\) 到它的路径有 \(\ge m\) 个右儿子那就不合法了。

猜测这个也是不合法的充要条件,换言之,只要满足上面的条件总能有解。

可以感知到除非 \(n\lt m\) 否则我们总能填一组数进去合法。

那么就变成了对二叉树计数,这样有一个暴力做 \(m\)\(f=\frac{1}{1-xf}\) 的做法,这里暂且不展开。

二叉树的计数用上面的方法转成一般树计数,则右儿子 \(\lt m\) 的条件就变成了深度 \(\le m\)

\(n+1\) 个点的树个数又等于 \(2n\) 长度的合法括号计数,所以现在的问题是:

计算长度为 \(2n\) 的合法括号序列个数,满足深度 \(\le m\)

然后回到最开始的网格图计数上来。

下面这个方法也许被叫做反射容斥?首先可以看出来这次多加了一条直线 \(y=x+m\),也就是被这两条直线给框住了。

如果只有一条直线,事实上存在一个容斥做法:我们考虑任何一条不合法路径都一定经过了 \(y=x+1\) 这条直线,考虑其第一次落在这里的位置,然后以 \(y=x+1\) 为直线将前面的部分对称过去(注意到 \((0,0)\) 一定对称到 \((-1,1)\)),所以任何一条 \((0,0)\) 开始的不合法路径都对应了一条 \((-1,1)\) 开始的路径;反过来 \((-1,1)\) 要到 \((n,n)\) 必须穿过 \(y=x+1\),那么这个时候翻折回去,又唯一对应了 \((0,0)\) 开始的一条不合法路径。

所以答案为 \(\dbinom{2n}{n}-\dbinom{2n}{n-1}\)(注意到你不管怎么对称,总步数都是 \(2n\),区别只不过在于两个维度分别要走的步数罢了)。

现在考虑加进第二条直线 \(y=x-m\)

首先有一个辅助公式在:\((X,Y)\) 关于 \(y=x+b\) 的对称点就是 \((Y-b,X+b)\)

注意到一条非法路径可能多次碰到两条直线,(这里有一个常规的容斥,需要分治 NTT 可以做到 \(O(n\log^2 n)\) 且常数不小),我们希望其只被计数一次。

考虑一条路径在第一次碰到上面的直线的时候算进去,之后第一次碰到下面的直线的时候排除,....;然后我们调换顺序,第一次碰到下面的直线的时候再把它算进去,之后第一次碰到上面的直线的时候再排除... 这样,不管你先碰到上面还是下面,最后这条路径就是被算了一次。

可以看出,两部分是类似的,以第一部分为例,第一次碰到上面直线,那就 \((0,0)\) 翻成 \((-1,1)\);下一次碰到下面直线,就把 \((-1,1)\) 翻过去,....,不断这样翻,翻 \(O(n)\) 次就好了。时间复杂度 \(O(n)\)

记录

2. Fibonacci: Revisited

这是一个常系数齐次线性递推,一个经典的方法是考虑其生成函数:

我们知道 \(f_n-\sum_{1\le i\le k}c_if_{i-k}=0\) (\(n\ge k\)),因此设 \(F(x)\)\(f\) 的生成函数,而 \(Q(x)\)\(c_i\) 的生成函数,则我们知道 \(F(x)-F(x)Q(x)\)\([x^k]\) 开始都为 \(0\)。因此我们考虑保留 \(f\) 的前 \(k-1\) 项的结果 \(R(x)\),令 \(P(x)=R(x)Q(x)\pmod {x^k}\),则有 \(F(x)(1-Q(x))=P(x)\),令 \(Q(x):=1-Q(x)\) 则有 \(F(x)=\frac{P(x)}{Q(x)}\)

因此我们要求的就是 \([x^n]\frac{P(x)}{Q(x)}\),我们知道 \(P(x),Q(x)\) 的项数都是 \(O(k)\) 级别的。

下面的算法被称为 Bostan-Mori 算法,也就是求两个多项式相除的 \([x^n]\) 结果,在 \(O(k\log k\log n)\) 时间内。

具体而言:考虑 \(\frac{P(x)}{Q(x)}=\frac{P(x)Q(-x)}{Q(x)Q(-x)}\)

注意到 \(T(x)=Q(x)Q(-x)\) 满足 \(T(x)=T(-x)\) 因此其是偶多项式:奇数项系数全部为 \(0\)

偶多项式有一个性质就是它的逆也是偶多项式。我们现在把 \(P(x):=P(x)Q(-x)\) 的系数奇偶分开成 \(p(x)\)(奇数)和 \(q(x)\)(偶数),则 \(\frac{p(x)+q(x)}{T(x)} = \frac{p(x)}{T(x)} + \frac{q(x)}{T(x)}\)

这个和式的左边只在奇数项不为 \(0\);右边只在偶数项不为 \(0\)

所以如果 \(n\) 是偶数,我们把 \(q(x),T(x)\) 的奇数项缩掉然后求 \([x^{\frac{n}{2}}]\) 即可;奇数同理。

这样我们只用做 \(O(\log n)\) 次多项式乘法,最后 \([x^0]\frac{p(x)}{q(x)}\) 容易求。

回到我们这里的问题,当 \(n\) 是奇数的时候(也就是最低位是 \(1\)),把 \(p(x)\)\(q(x)\) 的奇数项缩掉,然后相加变成的新的分子(原先我们只保留 \(p(x)\)),时间复杂度依旧是 \(O(k\log k\log n)\)

记录

3. Dice Sum Infinity

考虑我们第一次 \(\ge r\) 的时候,总会落在 \([r,r+6)\) 中的一个位置。(如果先到 \(r\),再到 \(r+1\),这是算在 \(r\) 的);然后考虑下一轮走完你又会落在某个 \(r+10^9+i(i\in [0,6) )\),以此类推。

这启发我们根据这个位置刻画状态,点 \(i\) 就代表我们当前这轮落在了 \(r+k\times 10^9+i\)

可以用矩阵快速幂算出第一轮落在 \(r+i\) 的概率和期望步数。注意期望 \(g\) 的计算是 \(g(i)=\sum (g(j)+f(j))\times \frac{1}{6}\),注意还要容斥掉一些东西(也就是保证是第一次 \(\ge r\) 的时候就踏在 \(r+i\) 了),其中 \(f\) 是概率。

然后这个问题被刻画成了有向图上的随机游走:我们可以算出每一轮某个点 \(u\) 到某个点 \(v\) 的概率和期望。当第一次游走到 \(0\) 的时候停止。且我们知道初始落在每个点的概率 \(p_i\)(其实也就是第一轮落在 \(r+i\)的概率)。

则考虑一条边 \(u\rightarrow v\)(注意 \(u\neq 0\))的贡献,首先这条边的期望可以用矩阵快速幂算,然后考虑它的概率:这里注意是所有经过 \(u\rightarrow v\) 的路径的概率和。首先 \(v\) 出去走到 \(0\) 的概率是 \(1\),因为不到目标就不会停,且这是个完全图;考虑所有情况走到 \(u\) 的概率,这个可以列方程高斯消元,也就是 \(F(u) = p_u + \sum_{v\neq 0}F(v)\times f(v,u)\)

最后还要考虑第一次的贡献,直接把每个 \(r+i\) 的期望加起来就好了。

感觉细节很多,而且非常难调。重构了一次才写对,而且还瞪了很久。

记录

4. 天桥

考虑 \(s=0,g=n-1\) 的部分分,那么横坐标的移动量显然就是 \(\Delta x\)(容易看出我们不会走回头路),那么考虑让 \(y\) 坐标尽可能少即可。

一个猜测是我们只关注每个桥的两个端点,这个好像是废话,问题是不能比较好地连边(我们希望是水平竖直这样连)。

容易发现我们只关注每个端点下面第一个经过这个楼的线段和楼的交点,然后就能做了。

回到一般情况会发现我们肯定是 \(s\) 往反方向走一段然后往 \(t\) 跑,跑过一段再回来这样的。\(s\) 往左走就是为了上一个比较高的桥,所以对于每个桥如果包含 \(s\),我们考虑 \(\lt s\) 的第一个 \(\ge y\) 的楼,这个地方就是上桥的关键点,对于 \(t\) 同理;但是值得注意的是:以包含 \(s\) 为例,你还要把 \(\gt s\) 的第一个 \(\ge y\) 的楼也考虑进去(部分分里的话,由于所有人的左端点都 \(\ge s\) 所以第一个 \(\ge y\) 的楼就是左端点),\(t\) 同理。

时间复杂度 \(O(m\log)\)

记录

5. 等这场战争结束之后

二操作肯定是建操作树后建立一个支持撤销的数据结构。那我们考虑加边和求连通块 k-th,肯定有并查集,这个也支持撤销;但是考虑 seg合并,平衡树等 polylog 的结构都不太能快速撤销;所以我们考虑分块来求 k-th,这样撤销的复杂度和合并是等同的。

所以我们可以做 \(\frac{n}{B}\) 次整个过程来定位每个询问的答案在哪个块里。

考虑散块,其实就是花费 \(O(B\log n)\) 的时间内查询每个数是否在并查集里。

因此时间复杂度是 \(O(m\frac{n}{B} + n\frac{n}{B}\log n + mB\log n)\)\(B\)\(\sqrt{n\log n}\) 的时候比较优,实测下来 \(B=2000\) 比较快。

但是为什么能这么快?

记录

6. 冒泡排序

首先取值范围肯定是 \(\{V\}\),然后我们来考虑性质 A。

对于 \(V=1\) 的区间,里面的所有数确定为 \(1\);然后考虑 \(V=0\) 的区间,去掉那些确定为 \(1\) 的数以后,首先区间里面至少还得剩一个数,然后如果两个 \(V=0\) 的区间是包含关系则大的可以去掉,接下来是若干个没有包含关系的区间,我们考虑最右边的那个区间,它肯定会选择最左边的点强制设为 \(0\),然后往前一些区间就已经满足了,不断做这个贪心。则最后变成这样一个形式:一些人确定为 \(1\),一些人确定为 \(0\),剩下一些人在 \(0/1\) 之间自由决策,问最小逆序对数。

\(n^2\) 的 dp 太 naive 了,我们观察到这样一个事情:对于所有自由决策的人来讲,为 \(0\) 的一定是一段前缀。

我们使用反证来证明:设 \(a_i\)\(\ge i\) 的位置确定是 \(0\) 的个数,设 \(a_i\)\(\le i\) 的位置确定是 \(1\) 的个数(这里排除所有自由决策的人),则我们能决定的逆序对数只有两部分:两个自由决策的人(第一类逆序对),或者是一个自由点 + 一个确定点的逆序对(第二类逆序对)。

假设有两个自由点(他们之间没有自由点)分别取 \(1,0\),则它们第二类逆序对贡献为 \(a_i + b_j\),互换以后是 \(b_i + a_j\),注意到 \(a_j \le a_i\)\(b_i\le b_j\),所以第二类逆序对的贡献减少了,而交换 \(1,0\) 显然也减少了一个第一类逆序对,所以我们就证明了序列的形态。

这样我们枚举分界点以后基本就能线性之类的计算了。

现在考虑性质 B,限制形式没有变,但是取值范围从 \(0/1\) 变大了。

我们依旧用上面的方法说明:自由点的取值是递增的。这样又能导出一个 \(n^2\) 的 dp,但这没有优化的余地;我们考虑难点在于要保证自由点取值递增,但是好处在于当自由点取值递增后第一类逆序对是 \(0\)

可以猜想:我们忽略自由点取值递增的约束,对于每个自由点,让他的第二类逆序对尽可能小,保证这件事情的基础上,一定存在一组递增的解。

证明也非常容易:假设两个自由点(位置递增)分别取了 \(x\gt y\),对于第一个人来说,既然 \(y\)\(x\) 劣,那么我们保留 \((y,x]\) 内的所有值,在它左边的个数要大于在右边的个数,这个偏序关系向后推到第二个人也成立,此时第二个人从 \(y\) 变成 \(x\) 会更优秀。

这样,我们只需要求出每个人的局部最优解,这可以很简单地扫一遍 + 线段树维护(区间加法,全局最小值位置),在 \(O(n\log)\) 的时间内性质 B 也得以解决。

现在考虑性质 C,容易发现,我们会强制让区间的第一个人固定为 \(v\) 然后剩下的人 \(\ge v\)

也就是比性质 B 强在,每个自由点都多了一个下界(性质 B 中下界可以认为是 \(0\))。

这里我好像导不出 \(n^2\) 的 dp 了,有点尴尬啊。

考虑套用性质 B 的这个结论(因为它看上去已经很强了),就是我们还是考虑每个位置,从全局最优解变成选大于等于下界的最优解。

考虑从前往后去证明:设我们选的是 \(x\),显然把 \(x\) 调整地更大既不让当前的位置变得优秀,对于以后的人影响也更大;那么我们把 \(x\) 调小成 \(y\ge v\),如果它有用,肯定后面有一个人是选了 \([y,x)\) 之间的某个数;而回顾性质 B 的相关证明,当在某个位置的时候,\(x\)\(y\) 优秀,那么我们一直向后都有 \(x\)\(y\) 优秀;所以后面是不会存在这种情况的。

这样 C 性质也在相同的复杂度内做完了(无非是全局查 minpos 变成了区间查 minpos)。

这样我们已经有 \(80\) 分了,考虑一般情况,无非就是转成 C 性质后的形态:也就是部分位置被钦定,剩下的位置被钦定下界。

我们首先知道每个位置的下界,问题是怎么选择恰好 \(=V\) 的那些位置。首先枚举 \(V\) 以后只有下界为 \(V\) 的数才是有意义的,套用 A 性质的做法:我们把包含他人的区间去掉后考虑最靠右的区间,选择它的左端点,然后去掉一些区间,以此类推。时间复杂度 \(O((n+m)\log n)\)

代码有点长,但不难写。

记录

7. 验题

考虑比较暴力的做法:我们从大往小枚举最长的 lcp 长度,然后再向后不断拓展,这需要我们支持:强制一个点在/不在独立集中,求当前独立集数量(答案可以和比较大的数取 \(\min\))。

这样就有一个 \(O(n^2)\) 的暴力了。考虑上述过程可以用 ddp 来加速。

具体而言设 \(a_u\) 表示点 \(u\) 能不能不选,\(b_u\) 表示点 \(u\) 能不能选。然后设 \(f(u,0/1)\) 是点 \(u\) 选/不选 dp 值,则有:

\[dp(u,0)=a_u\times \prod (dp(v,0)+dp(v,1)) \\ dp(u,1)=b_u\times \prod dp(v,0) \]

而这里有一个事情:当我们修改一个点的时候,若它是父亲的轻儿子,则注意到我们的乘积应该先除后乘,但由于乘积和阈值 \(V\)\(\min\) 所以不容易 \(O(1)\) 修改,这里可以对每个节点的轻儿子都维护线段树,则修改单点 \(g\) 的时间也是 \(O(\log)\) 的。复杂度其实没有变。

时间复杂度 \(O(n\log^2 n)\)

8. Forestry

一个想法是分开来考虑每个点作为连通块最小值的情况数,但这样我只会 \(n^2\),据说有进一步的 ddp 做法。

换个思路,考虑直接强行 dp:设 \(f(u,x)\) 表示 \(u\) 子树内根节点所在连通块 \(\max=x\)(我在这里反转了值域)的所有情况的贡献和(不考虑根节点所在连通块);直觉告诉我们想要转移还需要求 \(g(u,x)\) 表示方案数。

比较显然转移大概是 \(x,y \rightarrow \max\{x,y\}\) 的形式,我们推一下 \(g\),这个比较容易:

\[g(u,x)\times g(v,y) \rightarrow g'(u,x) \\ g(u,x)\times g(v,y) \rightarrow g'(u,\max\{x,y\}) \]

第一种对应断边,第二种对应不断。

然后来看 \(f\)

\[f(u,x)\times g(v,y) + g(u,x)\times (f(v,y) + val_y\times g(v,y) ) \rightarrow f'(u,x) \\ f(u,x)\times g(v,y) + g(u,x)\times f(v,y) \rightarrow f'(u,\max\{x,y\}) \]

这样的形式容易用线段树合并来维护,具体而言,我们看到我们需要维护三个东西,区间内的 \(\sum f,\sum g,\sum g_j\times val_j\)

转移的时候比较麻烦的是会出现这种:对区间的每个人,令 \(f:=f+g\);而常规的修改则是区间乘法。

这两个标记之间比较难以处理,不过我们坚定一点是能做的:因为如果我们维护向量 \([\sum f\,\sum g\,\sum g_j\times val_j]\) 则两种修改本质上都是乘矩阵。

我们注意到:矩阵除了主对角线以外,只有第二行第一列这个位置有值;所以可以直接维护四元组表示这四个位置的值;乘法就手动循环展开,这样效率其实本质上和直接维护 lazytag 是一样的。

时间复杂度 \(O((n+m)\log n)\),感觉还是非常快的啊。

记录

9. 数圈

首先若总和 \(S\lt 0\) 显然是非法的,因为整个过程的总和不变。

然后可以发现 \(S=0\) 的时候只有全零才是合法的:否则我们考虑最后一次操作,选的 \(a\) 如果不是 \(0\),则 \(-a\) 也不会是 \(0\);如果是 \(0\),则这次操作又是无意义的,就矛盾了。

接下来我们认为 \(S\gt 0\)

然后我们来研究一下操作过程实际上是交换相邻前缀和。(感觉比那个交换差分还典啊,怎么没有看出来/流泪)

由于是环所以做这样一个事情:把原序列复制若干遍,然后向左复制一边对应位置前缀和就 \(-S\),向右是 \(+S\)

合法也就是要求这个无穷序列的前缀和单调不下降。而交换操作是选择一个 \(i\),将所有模 \(n\)\(i\)\(i+1\) 的相邻位置同时互换。

考虑这是一个类似冒泡排序的过程:对于两个同余类 \(i,j\) 研究一下它们之间的贡献。

我们只用考虑两个同余类中,值在 \([0,S)\) 的那个人的位置关系就好了。

可以写出如下的暴力代码:

	rep(i,1,n)s[i] = s[i-1] + a[i];
	rep(i,1,n)rep(j,i+1,n){
		ll px=(s[i] >= 0) ? -(s[i] / S) : ((-s[i] + S-1)/S);
		ll py=(s[j] >= 0) ? -(s[j] / S) : ((-s[j] + S-1)/S);

		ll vx = (s[i] % S + S)%S,vy = (s[j] % S + S)%S;

		if(vx == vy)ans += abs(px-py) - (px>py);
		else if(vx < vy)ans += abs(px-py);
		else ans += abs(px-py) + ((px <= py) ? (1) : (-1));
	}

(感觉没有这段暴力很难继续做)。

至于更进一步地加速,注意到任意两项的差求和是好算的,三个调整量里第一个是二维数点,下面的是三维数点。这样就可以在 \(O(n\log^2 n)\) 的时间内解决。

似乎是可以 \(O(n\log n)\) 的,但我不是很会啊。

记录

10. Dead Cacti Society

这个显然和仙人掌直径很像。我们考虑建出圆方树以后 dp。

发现不太好设计状态,所以可以套一层二分,这样就可以设 \(f(u)\)\(u\) 子树内满足二分限制的情况下,最大深度的最小可能值(如果不能满足限制就是 \(\infty\))。

转移的时候枚举断边,对于环上直径和新的最大深度都可以讨论一下。

然后这里求边权比较麻烦,本来写的是 map,这样的话这个 \(\log^2\) 常数还挺大的,所以最后手写了一下哈希表。

时间复杂度 \(O((n+m)\log n)\)

记录

11. Push the Flow!

怎么又来仙人掌?

仙人掌最大流其实还是比较容易的:如果一条边不在环上,那么它本身的流量上限就限制了答案;如果你要从环上的 \(a\) 点流到 \(b\) 点,我们注意到有两条路径,这两条路径的边权 \(\min\) 之和即为这个环给答案的限制。

我们考虑建出圆方树。我们令顶点(也就是整个是方点父亲的那个圆点)位于第一个位置。则一个点流到顶点的流量就是:前缀的边权 min + 后缀的边权 min。

然后考虑在圆方树上做树剖。

如果一条边不在环上,则对其的修改是容易的;如果我们修改了环上的一条边,注意到整个环上的答案(也就是一个点到顶点的流量)都会变化;我们注意到这些边(体现在圆方树上市圆方边)只会有恰好一条重边;而对于剩下的轻边,我们可以单次 \(O(\log n)\) 求出这条边的值;而树剖的话只需要保证我们可以快速查询一条重链上的权值就行了。这个思想其实和 ddp 挺像的,感觉我好降智。

所以修改环的时候,首先在环对应的线段树上修改,然后更新那条重边的答案;在查询的时候对 \(O(\log n)\) 条轻边再分别求答案即可。

最后注意到如果 lca 是方点,则最后一次求的其实是一个环上任意两点的最大流;当然有线段树支持的话这也是容易做的,时间复杂度 \(O((n+q)\log^2 n)\)

另解:静态仙人掌上两点最大流有这个性质:对环来说,我们断掉边权最小的边,设边权为 \(v\),然后令所在环剩余边边权全部加上 \(v\);这样我们得到了一颗树,仙人掌上两点的最小割就是树上这两个点的最小割。

考虑带修就套 lct,时间复杂度 \(O((n+q)\log n)\)

如果用树剖,常数还是很大的,有两个优化:使用非递归线段树,以及记录环上 min 和 minpos(这样前后缀有一个是不用查的),不过第二个没写。

记录

12. Border 的四种求法

考虑建立 SAM,然后相当于找到一个最大的 \(p\in [l,r)\) 使得 \(lcs(p,r)\ge p-l+1\)

那么考虑用 SAM 建 parent tree,然后设 \(f(i)\)\([1,i]\) 位于的节点,则 \(lcs(x,y) = len(lca(f(x),f(y))\)

事实上:由于 \(len\) 越往上就会越小,所以 \(len(lca)\) 就是 \(f(x),f(y)\) 路径上的最小的 \(len\) 值。(也就是说 parent tree 同时也是一个类似笛卡尔树的结构,不过所有最小值缩在了一起。)

然后考虑这就变成了一个树上 DS 问题,给出一个点 \(x\),寻找最大的点 \(y\in [l,r],y\neq x\),然后令 \(x\rightarrow y\) 的最小值为 \(v\),有 \(v\ge y-l+1\)

考虑使用点分治来解决这个问题:我们把当前分治中心的子树内的所有点拿出来按照分治中心到它的路径最小值为关键字排序。则一条路径的 \(\min\) 就是两个人的关键字的较小值。

对于 \(val(y)\lt val(x)\),则 \(lcs=val(y)\),那么就有 \(val(y)\ge y-l+1\);对于 \(val(y)\ge val(x)\),有 \(lcs=val(x)\) 因此 \(val(x)\ge y-l+1\)

第一种情况,用 seg 维护每个位置的 \(y-val(y)\) 然后线段树二分就好了;第二种同理。时间复杂度 \(O(n\log^2 n)\)

另解:这个题还有 border 理论的做法,还不会,有空学习一下。

记录

13. 期望逆序对

这个题素质真差/fn

我们考虑计算每一对逆序对的出现次数。

设左边的人在 \(x\),右边的人在 \(y\);则对于除了 \(x,y\) 的所有位置都是等价的,因为两个人到达它们的概率相同。

所以两个人的位置分别只有 \(3\) 种可能,在 \(x\),在 \(y\),都不在;

然后去掉都在 \(x\) 都在 \(y\) 还剩七种状态,搞个 \(7\times 7\) 的矩阵快速幂就能算出来了。

然后每种状态对答案的贡献要么依赖 \(x\) 要么依赖 \(y\);枚举 \(y\) 以后用 bit 维护 \(x\) 的个数和 sum 就好了。

时间复杂度 \(O(\log k + n\log n)\)

记录

14. 星战

一句话题解,但是感觉非常难想:

考虑为每个点随一个点权,当存在一条边 \(u\rightarrow v\) 的时候就令 \(S:=S+w_u\),最后看 \(S\) 是否等于 \(\sum w_u\) 就行了。

记录

15. New Flight Routes

很神的线性做法!拜谢花花。

考虑 scc 缩点后的 DAG,设有 \(a\) 个无入度点,\(b\) 个无出度点,我们都知道答案是 \(\max\{a,b\}\),问题在于构造。

如果一个无入度点(左部) \(s\) 能到达一个无出度点(右部)\(t\),则反过来连 \(t\rightarrow s\) 就好了;但是 DAG 上的可达性也是 \(O(\frac{nm}{w})\) 的。

考虑如果 \(s\) 能到 \(t\) 我们就连边 \(s\rightarrow t\),然后寻找一组匹配。

设匹配对为 \((s_1,t_1),(s_2,t_2),...,(s_k,t_k)\),我们从 \(t_i\)\(s_{i+1}\),则这 \(2k\) 个点就强连通了。

所以如果原图存在一组完美匹配,则我们可以比较容易地构造,虽然连边看上去都是要利用 DAG 两点可达性。

考虑不存在完美匹配的情况,我们求最大匹配然后按照上面方式连边。

然后注意到对于左部任意一个不在最大匹配的边:至少有一个连向的点在最大匹配里。同理,对于右部某个不在最大匹配的边,至少被一个最大匹配里的点连到。

又因为最大匹配里的点在加上 \(k\) 条边后强连通,所以此时有性质:左部任意一个剩余点都可以走到右部任意一个剩余点。

此时就非常容易构造了:假设左边剩的多,设分别 \(a,b\) 个,则前 \(a\) 对就是 \(t_i\rightarrow s_i\),然后 \(t_1\) 向剩下的 \(s\) 连边,这样恰好连 \(a\) 条;右边多的话同理。

但是我们还是不能快速求最大匹配,建图的复杂度甚至都很高。

注意到我们并没有利用到最大匹配的很多性质:至少有一个邻居在匹配里并不是最大匹配的充分条件,所以我们只用找一组更弱的匹配就好了;事实上二分图匹配的时候贪心匹配得到的结果显然就是这样的解,体现在原图里只要贪心 dfs 就好了。

时间复杂度 \(O(n+m)\)

记录

16. Magic

感觉思维很强,怎么大家都秒了/ll

首先思考一下 \(2^npoly(n)\) 的暴力,如果我们从前往后记录则是不方便的,因为会有覆盖;所以反过来变成越靠前的操作优先级更高,这样加入一条线段的时候就可以计算位置个数了。

然后想一下这个过程,发现当我们加入一个 \([l,r)\) 的时候,如果 \(l-1\) 没有被加入那么这里就一定会有贡献;类似地如果 \(r\) 没有被加入这里也一定会有贡献。

又因为整个 \(l,r\) 互不相同所以每个位置只会恰好被某一个区间加入的时候算到一次。

然后考虑如果区间没有包含关系怎么做(如果没有相交且不包含,可以发现答案就是 \(2n\),所以这个肯定和正解无关)。

设位置 \(i\) 被挂在了区间 \(x\) 的左端点,如果 \(i,j\) 都同时被挂在左端点(或者反之)则它们肯定能安排一个合理的顺序(从小往大或者反之)使得全部合法;如果 \(j\) 被挂在了一个区间 \(y\) 的右端点那么可能会出现冲突,就是因为 \(i\) 要求在放 \(y\) 之前先放 \(x\)\(j\) 的要求和它相反。那就连边。

发现挂在左/右还刚好形成了二分图的形式,所以可以发现最后就是一个二分图最大独立集的问题。

对于一般情况,会发现出现包含的话肯定是先放小的,那其实是没有什么影响的。(小的挂着的位置不会被干涉,大的挂着的位置在外面,也不会被小的干涉)。

这样的话建图是 \(n^2\) 的但是跑起来是 \(n^3\) 空间也不太够,显式建图空间是够了但是时间不太行,考虑边连不满所以用 bitset 去存图,时空都是满足的。

时间复杂度 \(O(\frac{n^3}{w})\)

记录

17. 企鹅游戏

非常高妙的题。

考虑我们对模式串建出 ACAM,然后逐个加入文本串的字符,则我们会得到 \(|S|\) 个 ACAM 上的关键节点(可能有重);设一个模式串位于位置 \(u\),则其在文本串内的出现次数,就是 fail 树上 \(u\) 子树内关键点的个数。

但是这样的话一次加入最坏会把 \(O(L)\) 个节点都算进去。

我们证明:考虑 \(|S|\) 个关键点到根的链并,这个连通块里,把没有模式串的节点缩掉,然后考虑它的大小。\(m\) 个连通块的大小和不超过 \(L^{\frac{4}{3}}\)

这类证明常见的思路是分治:令 \(B=L^{\frac{1}{3}},\)对于长度 $\le $ B的模式串,考虑对于一个长度 \(len\in [1,B]\),所有长度为 \(B\) 的文本串在所有模式串的出现次数之和是 \(O(L)\) 的,所以这部分是 \(O(L^{\frac{4}{3}})\);对于长度 \(\gt B\) 的模式串,一个人最多在 \(\frac{L}{B}\) 个文本串里出现了,而这样的串又最多只有 \(\frac{L}{B}\) 个,所以这部分也是 \(O(L^{\frac{4}{3}})\)

那么我们考虑只要能找到这些关键点并且找到一组拓扑的顺序(或者暴力建树)然后就可以做了。

这个也比较容易:我们不断跳到祖先里第一个不被缩掉的点,如果当前点之前被跳过了,那就不再继续往上跳了。

时间复杂度 \(O(L^{\frac{4}{3}})\)

记录

这个问题还可以进一步泛化:相当于每个模式串有权重 \(w_i\),然后令 \(c_i\) 表示 \(s_i\) 在文本串里出现的次数,我们要求的就是 \(\sum a^{w_i\times c_i}\bmod p\)

首先任意 \(a^n\bmod p\) 可以在 \(O(\sqrt \phi(p))\) 时间内用预处理出来,这样一次算的时候就是 \(O(1)\) 的。

然后考虑这样一个做法:我们把整个问题离线,对于一个文本串,建出 \(|S|\) 个点的虚树,考虑虚树上一个点 \(u\),设其子树内有 \(cnt\) 个点,则根到 \(u\) 这一段每个模式串,在当前文本串出现的次数都应该是 \(cnt\),那么它对答案有 \(\sum a^{w_i\times cnt}\) 的贡献。

我们考虑由于虚树点数也是 \(O(|S|)\) 的,所以所求的这种链的信息总数是 \(O(L)\) 的。

然后考虑按照 \(cnt\) 分类,那么也就是有若干点,要求根到它这条链在 \(cnt=i\) 情况下的信息和。

依旧考虑忽略掉那些无意义的点,然后考虑这些点到根的链并上的所有点,设连通块大小和为 \(v_i\)\(\sum v_i\) 上限是 \(O(L\sqrt{\log L})\) 的。

很神奇吧.jpg

怎么分析的?可以看到,一个模式串的贡献,是它在所有文本串中本质不同的出现次数,设为 \(cnt_i\)。注意到这意味着它至少出现了 \(O(cnt^2)\) 次。

设长度为 \(i\) 的模式串有 \(c_i\) 个,则它们的出现次数和不超过 \(L\),由于 \(\sqrt{x}\) 是凸函数,根据经典按照斜率贪心,我们是把 \(L\) 次平均分给 \(c_i\) 个串的出现的时候取到最大值,所以它的贡献是 \(c_i\times \sqrt{\frac{L}{c_i}}=\sqrt{L}\times \sqrt{c_i}\),然后把 \(\sqrt{L}\) 提出来。

考虑 \(\sum \sqrt{c_i}\) 的最大取值(注意到 \(\sum c_i\times i\le L\) 的限制);这里不同的函数单次分配量不一所以不好按照斜率贪心,考虑转一下形式,相当于令 \(d_i:=c_i\times i\),保证 \(\sum d\le L\) 的情况下最大化 \(\sum \sqrt{\frac{d_i}{i}}\)

稳定情况肯定是大家导数(斜率)都相等也就是 \(\frac{1}{2}\sqrt{\frac{1}{id_i}}\) 都相等。那么可以看到 \(d_i=L\times \frac{1/i}{\sum_{j=1}^{L} 1/j}=\frac{L}{i\log L}\)

所以 \(\sum \sqrt{c_i}\) 的最大值是 \(\sum \sqrt{\frac{L}{i^2\log L}}\)。这里是 \(\sqrt{L\log L}\) 和提出来的 \(\sqrt{L}\) 结合得到 \(L\sqrt{\log L}\),不过常数很大的样子感觉。

18. Complete The Graph

么一问的力叩题捏,我们力叩太有实力辣。

考虑判掉比较显然的无解情况:也就是仅保留定边,若最短路已经 \(\lt L\) 则一定无解。

否则我们考虑选择一条路径出来,设其有 \(cnt\ge 1\) 条未定边,其边权和 \(\le L-cnt\) 然后我们可以给 \(cnt\) 条边分配边权使得这条路径长度为 \(x\)。剩下的全部设成 \(\infty\) 即可。

这样可以说明最短路 \(\le L\) 了但可能存在更小的一条路径。

注意到若存在一条更小的路径,则其包含的非定边集合 \(T\) 是我们选出的路径包含的非定边集合 \(S\) 的一个子集。所以要么它的非定边数更少,要么说明这条路径不是所有经过 \(|S|\) 条非定边里的最短路。

因此,我们对每个 \(i=0~n\),求恰好经过 \(i\) 条非定边的最短路,这个可以分层图;然后优先选择经过边数少的。时间复杂度 \(O(nm\log)\)

记录

后来发现有一个更优秀的做法,感觉很高妙:考虑最开始把所有非定边设成 \(1\) 然后每次轮流选一条边 \(+1\),则最短路最多增加 \(1\) 所以只要初始最短路 \(\le x\)(判掉 \(\lt x\) 且没有非定边的情况)就一定有解。那就二分一下好了,时间复杂度 \(O(m\log^2)\)

19. Split and Insert

这个操作看起来很吓人。但是考虑一下第一次操作,我们发现前 \(n-k\) 和后 \(k\) 个之间的顺序可以任意决定而它们内部的顺序要合法。

换言之 \(k=1\) 的时候我们就是把 \(1\sim n\) 分成两段,然后这两段的数在 \(p\) 中也是递增出现的。

考虑第二次,发现第一刀切出来的两段,都可以在结尾再切一刀(而且两段切的长度还不用相同)。依次类推就是你依次可以把之前切出来的所有段都切一刀而且长度是相互独立自由选择的。

这个看着就很区间 dp 了,然后可以设 \(dp_i(l,r)\) 是考虑还有最后 \(i\) 个操作没用然后要劈 \([l,r]\) 段的代价。时间复杂度 \(O(n^3k)\),常数非常小。

这里有个优化,就是我们可以贪心从前往后把极长连续的合法段缩在一起,然后其实变成了有若干个点,每个点之间都要被劈开的这个约束;当然如果 \(n\) 全是倒序它还是 \(O(n^3k)\) 的。

记录

20. Directed Vertex Cacti

神中神。

先考虑把环缩成点然后假设有 \(n\) 个点(注意不是题目里的 \(n\))。

考虑如果给定 \(n\) 个标号点,有多少方式把它连成一个恰好 \(m\) 条边的 DAG。

\(F_n(x)\) 是一个形式幂级数,\([x^m]F_n(x)\) 代表 \(n\) 点 DAG 连 \(m\) 边的方案数。

考虑转移有:\(F_n(x) = \sum_{a,b}\dbinom{n}{a}F_{n-a}(x)\times G_b(a,n-a)x^b\)

其中 \(G_b(a,n-a)\)\(a\) 个无入度点向后面的层里的 \(n-a\) 个点连 \(b\) 条边的方案数。

但是这样的话我们不能保证第二层的所有点都被第一层的边连到了。

换言之我们只能钦定一个点集 \(V\) 是无入度点,但不能保证其余的点都不是无入度点。

考虑容斥:\(F_n(x)=\sum_{b}\sum_{S}\sum_{S\in T}(-1)^{|T|-|S|}F_{n-|T|}(x)\times G_{b}(|T|,n-|T|)x^b\)

也就是我们枚举无入度点集 \(S\),然后根据容斥去枚举他的超集 \(T\)

考虑这个式子很大一部分程度上只和 \(T\) 有关,考虑枚举 \(T\) 然后只需要计算 \(\sum_{S\in T}(-1)^{|T|-|S|}\)

注意到 \(S\) 非空 因此这个式子就是 \((-1)^{|T|-1}\)

因此有 \(F_n(x)=\sum_{b}\sum_{T}(-1)^{|T|-1}F_{n-|T|}(x)\times G_b(|T|,n-|T|)x^b\)

把这个形式幂级数变成暴力做背包之类的应该可以用 DP 做到 \(O(n^2m)\) 之类的复杂度,但直接对着 dp 想肯定是没有前途的。

考虑让这个过程更加直观:也就是我们把 \(n\) 个点划分成若干层然后在不同层之间连 \(m\) 条边;一个层如果有 \(a\) 个点就贡献 \((-1)^{a-1}\) 的容斥系数。

回到原题来,我们把每个点先确定它在哪一层,然后把同一层的若干个点组成若干个环;最后根据每一层环的数量来计算。

设一层有 \(n\) 个点,考虑怎么求 \(\sum g(m)\times (-1)^{m-1}\),其中 \(g(m)\) 是把这 \(n\) 个点变成 \(m\) 个环的个数。

注意到:这个连环可以看作置换环,所以相当于是:有奇数个置换环的排列个数 减去 有偶数个置换环的排列个数。

注意到,有奇数个置换环的排列个数和偶数个置换环的排列个数在 \(n\ge 2\) 的时候是相等的。

所以 \(n\) 必须是 \(1\),然后每一层只有一个点因此答案是 \(n!\times \dbinom{\dbinom{n}{2}}{m}\)

酷。

记录

21. Minimum Element Problem

月初写过一个题 count 的题解。事实上这个题和 count 我认为是同类型的,都能归纳出很多套路计数出来。

并且根据其中一部分的启发写了一下卡特兰数自卷积 \(m\) 次形式的推导

首先考虑两个序列等价当且仅当笛卡尔树相同。

然后考虑给定一颗笛卡尔树,如何判断它标号为 \(x\) 的节点能填哪些数?

一个 naive 的想法是设深度(根节点深度为 \(1\))是 \(dep\)\(y\) 需要满足 \(y\ge dep_x\)

如果树是一条链,我们看出 \(y\ge dep_x\) 的下界是必要不充分的。我们再提出一个修正:子树大小(包括自己)\(sz\) 满足 \(n-y \ge sz_x-1\),也就是 \(y\le n-sz_x+1\)

因此 \(y\) 的取值范围是 \([dep_x,n-sz_x+1]\) 且容易验证:\(dep_x\le n-sz_x+1\) 以及这个条件的充分性。

由于第一点的成立,考虑差分:对于一颗树,在 \(dep_x\)\(+1\),在 \(n-sz_x+2\)\(-1\)。现在问题转为:对于每个 \(i\in [1,n]\),分别求 \(dep_x=i\)\(sz_x=i\) 的笛卡尔树数量。我们对两个问题分开来考虑。

对于第一部分,考虑从 \(x\) 一直向上走到根的过程,把过程分为向左跳和向右跳两部分。特殊地,我们认为在 \(x\) 节点既有一次向左跳也有一次向右跳。

对于所有向左上跳到的节点(包括 \(x\)),考虑它们本身 + 它们的左子树构成了 \(\le x\) 的位置全体;对于所有向右上跳到的节点(包括 \(x\)),考虑它们本身 + 它们的右子树构成了 \(\ge x\) 的位置全体。

因此我们分别枚举向左跳和向右跳的步数 \(i,j\)(注意 \(x\) 节点分别往 \(i,j\) 贡献一次),以左边为例:把 \(i\) 个节点拉出来挂在一条向右的链上,这样 \(i\) 个树连成了一个二叉树;运用左儿子右兄弟表示法等价于一颗根节点恰好有 \(i\) 个儿子的树也就等价于一个最外层有 \(i\) 对括号的长度为 \(2\times x\) 的括号序列个数,这部分的计算参见上面的 link。

然后把 EGF(注意如果是 \(i\) 步则卷 \(fact_{i-1}^{-1}\),最后结果乘的也是 \(fact_{i-2}\),因为 \(x\) 这个人的顺序永远是第一)卷起来就好了。

对于第二部分,首先考虑把 \(x\) 子树缩成一个点,这样问题变成了一颗 \(n-i\) 个节点的笛卡尔树且中序遍历上一个固定位置(根据 \(x\) 左子树大小决定)\(a\) 的编号是 \(x\) 的方案数。

这个问题无论 \(a\) 是多少都等于 \(n-i-1\) 个节点的笛卡尔树数目:考虑建立一一对应,每个 \(n-i\) 个节点的笛卡尔树删去第 \(a\) 个点后唯一得到 \(n-i-1\) 的笛卡尔树;反过来确定插入位置也是唯一的。

然后考虑内部如何分配,左子树最多分配 \(x-1\) 个点,右子树最多分配 \(n-x-1\) 个点,所以把左右的信息卷起来即可。

这样瓶颈是两次卷积,其余部分线性,时间复杂度 \(O(n\log n)\)

酷!

记录

22. 大毒瘤

考虑这个看上去不是很能 polylog,考虑暴力点的想法,我们直接维护所有没着火的连续段。

如果一个段长度小于等于根号,则根号次时间后它会清零;如果一个段长度大于根号,任意时刻这样的段最多只有根号个。

三操作最多新增一个段;四操作把一些段合并起来。

所以可以看出所有时刻段的总和是 \(O(q\sqrt n)\) 级别的。

然后考虑我们暴力维护所有连续段就好了。

考虑这样我们要支持区间加单点求值,可以写一个分块。

然后还有个问题就是关于着火的格子清零这个事情,可以假装看不见,然后四操作推平的时候直接暴力把区间里的着火格子都拿出来清零就好了,这部分的点数也是 \(O(q\sqrt n)\) 的。

记录

23. Airplane Boarding

谔谔模拟还把这个题上树的,素质真差。

考虑按照题意模拟没有什么出路,我们把这个问题转成更形式化的一些问题。

对于一个局面可以设 \(f_u\) 代表从根下一次走到点 \(u\) 是什么时刻。然后考虑当前加入一个垃圾 \(i\),从根到 \(i\) 的路径上若有一个点 \(u\),有约束:\(u\) 下一次变空是在时刻 \(g_u\),则它到达 \(i\) 的时刻至少为 \(g_u+(dep_i-dep_u)\),所以考虑可以维护根链上最小的 \(g_u-dep_u\),然后加入一个点的时候就可以算出它到达的时刻,进而更新答案;然后考虑他对 \(g\) 的修改,首先它这个位置的 \(g\) 被更新了,然后对于向上的根链会做一个类似 upmax 的东西:\(g_{fa}:=\max\{g_{fa},g_u\}\),这样每次暴力更新 \(f,g\) 就是 \(n^2\) 的。肯定比直接模拟好写很多。

注意 \(g\)\(f\) 的区别,一个例子是:可能某个时刻一个点为空,但是他的祖先被堵住,这种情况下 \(g\) 就会比 \(f\) 小。

考虑原题在链上的做法:我们注意到向上 upmax 这部分肯定比第一部分困难,那考虑直接把所有点的信息往上推一个(代替 upmax),向上推的话之前被影响的人(一定是子树里的)依旧会被影响所以没有什么问题,一个特殊的 case 是根节点的 \(g\) 向上推不动了,这里确实是 upmax 了。

这样就变成区间移位了,直接 fhq 完事就是 \(O(n\log n)\)

上树的话也就树剖一下罢了,时间复杂度 \(O(n\log^2 n)\)

记录

24. Ball Collector

我去这不是我们填数游戏吗,没想到在这里看见了,下次转载记得标明出处捏。

考虑给定 \(n\)\((a_i,b_i)\) 如何让选出来的集合最大化。

考虑连边 \(a_i\leftrightarrow b_i\),每个连通块的选择是独立的:如果是树,则我们只能选择 \(sz-1\) 个点,否则一定能把 \(sz\) 个点都选上。

考虑在树上 dfs 的时候把答案全部求出,用带撤销的并查集维护:我们需要维护连通块大小和内部边数。时间复杂度 \(O(n\log n)\)

记录

25. Turtle

比较容易发现肯定会把最小的两个放左上右下,最大的两个放左下右上。

更进一步可以感知到肯定是第一行递增第二行递减。

因此两行的前缀和函数都有凸性。

若拐点不在 \(1/n\) 处可以发现往左或者往右(因为有凸性)至少有一个更优,所以拐点不在第一列就在最后一列。

考虑把最小的两个(必定拿到)扔掉以后,剩下 \(2(n-1)\) 个,相当于划分成两组 \(S,T\) 使得每组都 \(n-1\) 个且 \(\max\{S,T\}\) 最小。

也就是选出 \(n-1\) 个,在和大于等于一半的情况下最小。

做个背包就可以,因为是可行性可以用 bitset 优化,时间复杂度 \(O(\frac{n^3V}{w})\)

记录

26. Wise Men (Hard Version)

感觉这个题素质不是很高,因为 \(n\) 开大很容易卡常,开小容易被折半草过去?

考虑把这个要求的东西子集反演掉,也就是钦定若干个间隔必须连边,这样相当于用若干条链拼出整个排列。

可以在 \(n^22^n\) 的时间内对任意集合 \(S\) 求出点集是 \(S\) 的链的个数,然后考虑枚举链形态再做什么东西就很恐怖,但是注意到本质不同的数量只有 \(p(n)\) 种,所以这部分并没有那么大。

然后后半部分就是一个 fwt_or 了,可以把 \(n\) 个 fwt 数组都预处理出来,每次直接把 \(O(n)\) 个数组点乘就好,这样时间复杂度就是 \(O(n^22^n + p(n)n2^n)\),反正被卡常了。

记录

27. Fedya the Potter

首先考虑区间 gcd 这个东西很显然可以在 \(O(n\log^3 V)\) 的时间内求出整个桶,然后我们缩掉不存在的那些位置。由于 \(n,V\) 差异很小可以认为桶的大小就是 \(O(V)\) 的。

考虑中位数用二分转成统计多少个 \(\le k\) 的区间大于等于 \(mid\)

这里比较暴力的是 \(O(n^2)\) 双指针,这样就没有利用缩段的性质。

然后考虑枚举两个端点所在的段(判掉在同一段的情况),然后只有两种可能:取任意个都合法;取满不合法。

取任意个都合法是容易判的,也双指针一下;取满不合法但是两边至少可以取,也就是意味着 \((l+1)~(r-1)\) 不满但是 l~r 满了。

这个第一眼看着很能双指针(对于 \(l\) 分别求出左右边界),但是感觉总个数不太 \(O(V)\) 的样子,后来摸鱼酱解释了一下发现确实:就是考虑两个相邻的 \(l\) 的可能的右端点区间集合交至多为 \(1\) 所以还是 \(O(V)\) 的。

然后问题变成了每次给定 \(x,y,a,b,S\)\(\sum_{i\le x,j\le y}[ai + bj\le S]\) 的个数。

这个就是类欧,做完了。但我场上不会类欧啊,酷的。

时间复杂度 \(O(V\log^2 V)\)

记录

28. Messages on a Tree

感觉思想和前几天那个奶牛题很想(长的也贼像):就是考虑把这个问题转成比较可做的 DS 问题,容易看出我们只需要求每个点到哪个点 roll_back 了就好了。

如果 \(x\)\(u\) roll_back 了,那么路径上从 \(x\)\(u\)(不含 \(u\))的解锁时间都会被重置。

不过问题是我们发现能堵住你的人不一定在你之前就加进去了。

如果 \(x\)\(u\) 被一个 \(y\)\(f\) 的人(还要回来)堵了,则说明:\(x\)\(u\) 的时候 \(y\) 已经到过了,且还没有走回去。

则两个偏序存在:\(t_x + dep_x \gt t_y + dep_y\)(相同的时候比较编号),以及 \(t_y+dep_y+dep_u-2dep_f \gt t_x + dep_x - dep_u\)

第一个偏序告诉我们,只需要按照 \(t_y+dep_y\) 的顺序去考虑询问,则干扰点一定会在之前都考虑到。

第二个偏序就转到 DS 上去解决,也就是 \(t_y+dep_y + 2dep_u -2dep_f\)。那么每次问出一个点 \(y\)\(f\) 以后,把 \(y\)\(f\)(不含 \(f\))的值都修改掉,查询 \(f\) 的时候树剖 + 线段树二分就行。

时间复杂度 \(O(m\log^2 n)\)

记录

29. 分糖果

一个比较自然的想法是我们只需要求出最后一次触顶或者触底。

事实上最后一次越界是比较难直接求的,但是考虑一次触底和一次触顶之间的 \(\max-\min\) 肯定 \(\gt s\) 所以可以二分出一个最长的 \(\max-\min\le s\) 的后缀,这一段的越界要么全部触底要么全部触顶。然后根据 \(\max\)\(\min\) 就能比较容易地判断并算出来。

这样如果给若干个操作我们会快速做了,如果只有一个点可以建线段树然后 seg 二分;多个点考虑打差分离线下来 seg 合并。

时间复杂度 \(O((n+m)\log n)\)

记录

30. Popcount Sum

与其在二进制下判断 \(x\) 是不是模 \(m\)\(r\) 不如对每个 \(km+r\) 算它的 popcount。

然后做 \(O(\log n)\) 次类欧。

记录

posted on 2023-05-03 19:08  Cry_For_theMoon  阅读(278)  评论(1编辑  收藏  举报