如题
Comet OJ round6 D另一道树题
题目链接:https://www.cometoj.com/contest/48/problem/D?problem_id=2280
solution:设$f(n)$表示有多少种方案可以使得$n$步之后游戏不结束。答案即为$\sum_{i=0}^nf(i)$
我们在求一个$f(k)$的时候,我们可以考虑下面这种思想:将所有走$k$步后在汇聚在同一终点的点集称为一个等价类,那么$f(k)$即为所有等价类的$siz+1$的乘积并减去$n+1$(减去空集和只选一个点)
这些等价类是互相合并得到的,多个$k$步的等价类可能会合并成一个$k+1$步的等价类。等价类合并有两种,一是在$lca$处合并,二是所有深度小于$k$的节点都会变成一个$k$步的等价类,第二类等价类我们直接计算,主要考虑第一类等价类。
本人使用的是长链剖分,维护每个等价类被建立时的步数,当一个等价类用于合并时,相当于从被建立时的步数一直到现在合并时的步数减1这段贡献都要乘$siz+1$,相当于对$f$的区间乘法,直接在前缀积数组打标记,最后再计算即可。然后再进行合并,当前合并时的步数即为这个新的等价类被建立时的步数
最后要记得扫一遍根所在的链来更新$f$,然后直接扫前缀积函数就可以得到$f$并计算答案,配合线性求逆元直接做到$O(n)$
1 | //by hdmmblz,长链剖分 |
Comet OJ round 7 C 临时翻出来的题
给定一个$n$元数列$A$,值域$[1,n]$,合法的$n$元排列指的是这个排列$i\in[1,n],pos_i\neq a_i$,对于合法排列中的每个逆序对$i<j,pos_i>pos_j$,都会产生$|i-j||pos_i-pos_j|$的贡献,求所有合法排列的贡献之和。
$n\leq16$
这题并不太难,毕竟放在了$C$,只是我当时现场想出的是$O(n^6)$的算法,渐进意义上比标准题解的$O(n^22^n)$要优,所以记录一下。有趣的是,当$n=16$时,这两个算法的时间复杂度刚好相同。
指数级算法去看官方题解即可,这里我就只说说我的多项式时间的算法,其实也非常简单,就一句话:枚举$i,j,pos_i,pos_j$,然后相当于询问有多少个合法排列可以把剩下的$n-2$个数和位置配对,这里直接跑一个$O(n^2)$的容斥背包即可。
1 |
|