首先总结一下前段时间遇到过的一些有意思的题。
Round #474 (Div. 1 + Div. 2, combined) Problem G
其实关键就是n这个数在排列中的位置。
这样对于一个排列,设$f[pos] = p$, 那么从位置$1$到位置$pos$最大值被刷新了$a$次,从位置$n$到位置$pos$最大值被刷新了$b$次。
去掉$n$之后,剩下$n-1$个数被分成了两个部分。
假设把这$n-1$个数分成$a+b-2$个组,分配给左边$a-1$个组,给右边$b-1$个组。
对于$n$左边的数,每个组内部一定满足第一个数最大,对于$n$右边的数,每个组内部一定满足最后一个数最大。
这样就满足了题意。
这样其实就是一个环排列计数,具体一点,就是求$n-1$个数划分成$a+b-2$个集合,每个集合内部再按特定顺序围圈分组的方法的数目。
这刚好是第一类斯特林数。那么答案为$C(a + b - 2, a - 1) * S(n - 1, a + b - 2)$。
Round #480 Div2 Problem E
去掉$k$个点,相当于保留$n - k$个点,需要满足剩下的$n - k$个点连通。转化为保留$m$个点,求留下的点的权值和最大。
以$n$为根(必选),从$n - 1$开始往前选,假设当前已经选了$x$个点,如果当前点往上爬,爬到第一个已经被选的点时的移动距离大于$m - x$,
那么不能选这个点(因为选了一个点就必须选他的祖先),否则就选入这个点,然后选择所有的他的祖先中未被选择的点
(也是一步步往上爬,到发现了被选中的点为止),到选了$m$个点为止结束即可。
Round #482 (Div. 2) Problem D
预处理出所有数的因子。加入一个数的时候在以他的所有倍数为编号的字典树中插入这个数,(字典树编号最大为$100$)
查询的时候如果$k$小等于$100$,那么在字典树里查询,否则直接暴力找。
Round #383 (Div. 1) Problem D
首先预处理出$c[]$,$c[i]$表示$i$到根上所有边的每个字母出现次数总和的奇偶性,状态压缩后用一个数表示。
如果满足$c[x]$ ^ $c[y] = 1$,$x$到$y$的路径上的所有字母重排后就可以组成一个回文串。
考虑dsu on the tree,对于每个点,求出$f[x]$:满足$c[i] = x$的所有$i$的深度的最大值。
在遍历轻儿子的所有后代的时候一边更新最大值一边刷新$f[]$就可以了,重儿子的方法类似。
Round #316 (Div. 2) problem (E)
设$f(i, x1, y1, x2, y2)$表示A从左上角出发走了$i$步到达$(x1, y1)$,B从右下角出发走了$i$步到达$(x2, y2)$的方案数。
看似是$5$维的状态,其实显然可以转化成$3$维,因为知道了$x1$就知道了$y1$,知道了$x2$就知道了$y2$。
枚举$i$,每次$x1$和写$x2$有一个特定的范围,总状态不是很多。用滚动数组可以把数组降到二维。
最后统计答案的时候判断一下奇偶就可以了。
5.22
Round #483 Problem C
状态表示$dp[i][now][a][b][c]$, $i$表示第$i$个人此时正在电梯里,前$i-1$个人要么正在电梯上,要么已经到达了目的地,$now$代表当前电梯正停在第$now$层,$a$, $b$, $c$代表正在电梯里的三个人的目的地。
记忆化搜索转移即可。
5.28
Avito Code Challenge 2018 Problem E
考虑这样一个事实,如果某个和能被表示出来,那么这个数就可以成为最大值。
那么线段树上跑背包就可以了,用bitset优化。
时间复杂度$O(nqlogn / w)$
5.29
Edu Round 44 Problem G
考虑容斥。
首先不管冲突,计算答案,对于任意一个三元组,只要他是三元组就加到$ans0$。
然后对于任意一个三元组,如果他存在任意一条边(每条都判),那么就加到$ans1$。
接着对于任意一个三元组,如果他存在两条边(每两条都判一次),那么就加到$ans2$。
最后把所有三元环加到$ans3$.
这样,对于任意一个三元组
如果他有$0$条边,那么他被$ans0$计入了$1$次,最后计入了答案。
如果他有$1$条边,那么他被$ans0$计入了入了$1$次,被$ans1$计入了$-1$次,最后对答案贡献是$0$。
如果他有$2$条边,那么他被$ans0$计入了入了$1$次,被$ans1$计入了$-2$次,被$ans2$计入了$1$次,最后对答案贡献是$0$。
如果他有$3$条边,那么他被$ans0$计入了入了$1$次,被$ans1$计入了$-3$次,被$ans2$计入了$3$次,被$ans3$计入了$-1$次,最后对答案贡献是$0$。
那么就符合题意了。
Round 485 Div1 Problem C
暴力+记忆化搜索。
枚举到一个集合的时候如果发现这个集合还没标记过(也就是还没连通过),那么累计答案。
然后就把跟这个集合可以连边的所有点全部加入这个连通块,具体操作是按位异或之后标记,并对所有子集标记
感觉还是挺考智商的一个题。
6.6
Round 485 Div1 Problem D
先快速幂求出$3^{x}$,满足$4 * 3^{x} <= n$,然后逐渐逼近。
乘法的时候要用FFT优化,注意一些细节。
6.7
Round 429 Div1 Problem C
首先其实这是若干个连通块的事情。
因为如果$a * b$和$b * c$都是完全平方数,那么$a * c$肯定是完全平方数。
所以这$3$个数两两都不能在一起。
然后就变成了HDU6116那个题。搞出卷积,然后暴力(甚至不用NTT)容斥就可以了。
6.8
用FFT匹配字符串的经典问题,就是加了一个门限值$K$
因为只有$4$个字符,所以提取出$4$个$01$序列。
把S串对应的$01$序列每个$1$位置前后$k$个都变成$1$,然后按照套路来就可以了。
6.9
Round 485 Div1 Problem E
首先$10^{7}$以内所有数最多只有$8$个质因子。
那么对每个数分解质因数,然后把询问拆开来,对每个质因子独立求解。
可以证明所有质因子要处理的信息的和不超过$nlogn$个。
把问题转化为求某个点到根结点这条链上的$min(a[i], x)$的和。
于是就想到了排序,然后一个个加进树状数组。
维护两个树状数组,每次把那些小于询问的加到第一个,把那些已经大于询问的从第二个减去。
(脑补一下这个过程)
至于树状数组怎么操作,回想一下差分的思想。
搞出dfs序之后如果要加上某个点的值,那么对这个点代表的dfs序区间差分一下,然后单点求值。
最后把询问的答案整理一下就可以了。
6.13
最近的两场比赛加起来掉了$160$多分……心累。
直接回蓝名。
主要是后面的题不会,中间的题卡了太久,以及前面的题FST。
教育场就是教育场吧,前面后面的题权重都一样,都是$1$
这教育场的G我怎么就去写点分治了啊……完全没必要的。
所以跳题是真的亏,这也说明了我垃圾的读题能力。
div2最近加大了一些难度,个人觉得Round 487并不是一场很好的比赛,题目难度有点偏高了。
(以及有点毒瘤)
6.14-7.29
woc快两个月了我一点都没写过。
慢慢填坑
F 直接固定一棵生成树然后dfs一遍就好了。
G 树形DP一下就可以,没必要点分治。注意儿子的信息用完之后得清空,不然会MLE
E 固定生成树之后并查集(类似17沈阳网络赛那个套路),求出每条边的新权值
(如果是必经之路那么为$1$,否则为$0$)
然后求一下直径就行了。
F 直接线段树就好了。离线操作就行。
FFT裸题
D
其实只要求出每棵树的$dp[x][k]$就行,也就是从$x$出发走$k$步再回到$x$的方案数。
直接求显然很难,考虑树分治。
给每个点加一个强行必须经过的点,然后计算贡献。
这样在树分治的过程中一个点的经过区域刚好被那些分治中心划分成了最多$log$个区域
分治的时候DP两个东西,一个是从分治中心出发经过$k$步最后到某个点的步数。
还有一个是从分治中心出发经过$k$步中途不能回来并且最后到某个点的方案数。
对当前子树的某个点的答案贡献就是$∑f[x][i] * g[x][k - i]$
也就是枚举一个点经过了多少步第一次到达分治中心,然后在分治中心开始兜兜转转,
最后回到自己。
最后两棵树的答案求一下卷积和就行了。
考虑每个点往上走一次路线最高能走到哪里。
然后倍增一下。
询问的时候先跳到跳一步就能到LCA的那个位置,
记作$x$和$y$,先判断能否到达。
然后讨论一下,如果存在一条两端分别在$x$子树和$y$子树里面
就可以直接到了,否则答案还要加$1$
这是一个二维数点问题,直接离线树状数组就可以了。
首先考虑哪些点要被考虑。
新加的边两端的点,这些点到根的所有点。
最多$240$个点,构成了一张新的无向图。
每个点是带权的,权值为这个点管辖的点数。
然后枚举起点,搜索一下简单路径个数即可。
G 动态开点线段树跑一下就可以了。
高中学弟上黄题!
回滚莫队直接艹过去了……