2020-10-22刷题笔记

CF14D(自己做出来的)

枚举其中一条路径,然后将这条路径上所有边权都设为 − ∞ -∞ ,再用 d p dp dp贪心地跑一遍直径即可,取这两条路径的乘积的最大值即为答案。

时间复杂度 O ( n 3 ) O(n^3) O(n3)

P3501(自己做出来的)

首先,挖三个性质。

①如果字符串 s s s为反对称串,那么 s s s的长度为偶数。否则中间那个数,经过反转后交换仍然在那个位置;而不可能将一个 0 / 1 0/1 0/1翻转后还是原来的数,所以长度不能为奇数,只能为偶数。

②如果字符串 s s s为反对称串——设 m i d mid mid为字符串 s s s的中间位置偏左的那个位置,那么有 m i d − 1 mid-1 mid1这段子串与 m i d + 1 , r mid+1,r mid+1,r反转后的子串相同。

③对于相同的 m i d mid mid,如果 l − r l-r lr这一段满足要求,那么对于所有的 l 1 − r 1 ( l ≤ k 1 ≤ m i d ) l_1-r_1(l≤k_1≤mid) l1r1(lk1mid)都满足要求,即存在单调性

于是,我们枚举这个 m i d mid mid,每次二分找到最靠左的 l l l。至于二分中套的 c h e c k check check函数,我们使用哈希实现即可。

时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)

P3498(自己做出来的)

对于每个区间,我们的新哈希值为这段区间从前到后的哈希值从后到前的哈希值

我们每次枚举长度 k k k,然后扫一遍整个序列,对于每个区间我们把这个区间的两个哈希值 u , v u,v u,v,如果 u ≤ v u≤v uv那么我们把 [ u , v ] [u,v] [u,v]这个 p a i r pair pair扔到一个 s e t set set平衡树里面去,否则把 [ v , u ] [v,u] [v,u]这个 p a i r pair pair扔进去。

根据 s e t set set的维护复杂度为 l o g n logn logn,再由于调和级数的影响,时间复杂度为 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)

CF109C(自己做出来的)

考虑反面计数。

我们只连不 L u c k y Lucky Lucky的边。对于每一个不 L u c k y Lucky Lucky的连通块,假设其大小为 k k k,那么对反面的答案的贡献为 A k 3 + 2 k ( n − k ) ( k − 1 ) A_{k}^3+2k(n-k)(k-1) Ak3+2k(nk)(k1)

为什么呢?这个 C k 3 C_k^3 Ck3表示,三个节点都在这个连通块中是不行的。另外,我们可以在这个连通块中先选一个节点作为 i i i,然后再选择一个节点作为 j j j,其中选择 j j j的方案有 k − 1 k-1 k1种;最后再选择一个在这个连通块外的节点,有 ( n − k ) (n-k) (nk)种选择。但是, j j j k k k可以交换位置,所以最后的最后还要再乘上一个 2 2 2

使用并查集求出每个连通块大小,最后用总数 n ( n − 1 ) ( n − 2 ) n(n-1)(n-2) n(n1)(n2)减去它,并注意取模即可。

时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)。若使用按秩合并并查集,时间复杂度会优化到 O ( n ) O(n) O(n),但这样并没有必要。

CF29D(自己做出来的)

又是一道远古场的题

对于每个叶子节点,我们在那里记录下它是第几个被访问到的。

然后,我们递推上去, d p i dp_i dpi表示在以 i i i为根的子树中,第一次访问这个子树中的叶节点是第几次。

最后,我们从根节点开始深搜下去,对于一个节点的多个儿子,先搜 d p dp dp值小的,再搜 d p dp dp值大的;记录下我们搜到的叶节点的队列,深搜完判断一下是否满足要求即可。

时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)。为啥 n ≤ 300 n≤300 n300啊……

CF461B(我太菜了,没做出来,感谢duyi巨佬)

一道不错的树形 d p dp dp题。

状态设计: d p i dp_i dpi表示以 i i i为根的子树的信息。 d p i , 0 dp_{i,0} dpi,0表示, i i i这个节点所在的连通块还没有黑节点, d p i , 1 dp_{i,1} dpi,1则相反。

状态转移式:

dp[now][1]=(dp[now][1]*(dp[e[i].to][0]+dp[e[i].to][1])+dp[now][0]*dp[e[i].to][1])%mod;
dp[now][0]=(dp[now][0]*(dp[e[i].to][0]+dp[e[i].to][1]))%mod;

这里的e[i].to表示 n o w now now节点的儿子节点。

什么意思呢?我先阐释一下第一个式子。当前 n o w now now这个节点所在连通块已经有黑节点了,那么,如果遇到孩子节点所在连通块还没有的,直接带上它;否则,直接断开,即 n o w now now这个节点所在连通块不进入这个孩子节点的子树。同时,如果原来 n o w now now这个节点所在连通块还没有黑节点,并且当前这个儿子节点所在连通块是有的,那么就带上它,即加上 d p n o w , 0 × d p e i . t o , 1 dp_{now,0}×dp_{e_i.to,1} dpnow,0×dpei.to,1的意义。

d p n o w , 0 dp_{now,0} dpnow,0的意义相同,这里不再赘述。

时间复杂度 O ( n ) O(n) O(n)。我太菜了……

P3538(我太菜了,没做出来,感谢忆殇巨佬)

还是一道哈希题,挖性质……

①如果 n n n的循环节长度为 k k k,那么一定有 k ∣ n k|n kn

如果 n n n的循环节长度为 k k k,当且仅当 [ l , r − k ] [l,r-k] [l,rk]这段区间与 [ l + k , r ] [l+k,r] [l+k,r]这段区间相同

于是,我们预处理约数,每次枚举 k k k,使用哈希 O ( 1 ) O(1) O(1)判断即可。

时间复杂度 O ( q l o g n ) O(qlogn) O(qlogn)

②这么显然都没想到,我太菜了……

P4551(学算法)

在这里学会了 T r i e Trie Trie树。

板子题,没题解。

P3371(复习算法)

在这里复习了 S P F A SPFA SPFA

板子题,没题解。

CF1292C(神仙题,没做出来,感谢syksykCCC巨佬)

突然想到这一天没有做神仙题,于是决定做一道大神仙题,于是就选了这一题……

还以为这题是贪心,可是怎么搞都有反例,于是就上了 d p dp dp……结果状态设计不停地错误,甚至连 O ( n 7 ) O(n^7) O(n7)解法都出来了……醉了。

于是就开了题解。

首先,思考一个东西:如果一条路径的 m e x mex mex r e s res res,说明什么?说明: 这条路径经过了所有权值为 1 1 1 r e s − 1 res-1 res1的边。

然后,我们发现,我们要最大化的是 ∑ i = 1 n ∑ j = 1 n m e x ( i , j ) \sum_{i=1}^n \sum_{j=1}^n mex(i,j) i=1nj=1nmex(i,j)

颓一波式子:

∑ i = 1 n ∑ j = 1 n m e x ( i , j ) \sum_{i=1}^n \sum_{j=1}^n mex(i,j) i=1nj=1nmex(i,j)
= ∑ k = 1 n k ∑ i = 1 n ∑ j = 1 n [ m e x ( i , j ) = k ] =\sum_{k=1}^n k \sum_{i=1}^n \sum_{j=1}^n [mex(i,j)=k] =k=1nki=1nj=1n[mex(i,j)=k]
= ∑ k = 1 n c n t ( k ) =\sum_{k=1}^n cnt(k) =k=1ncnt(k)

是不是想到了联想到了可爱的莫反

这里, c n t ( k ) cnt(k) cnt(k)表示,满足路径的 m e x mex mex不小于 k k k的路径的数量。

接着,想到了可爱的 d p dp dp也许因为我不够可爱,导致无法触碰到可爱的 d p dp dp吧。

状态设计: d p i , j dp_{i,j} dpi,j表示 i i i j j j这条路径包含了所有 0 0 0 l e n − 1 len-1 len1的权值, l e n len len表示这条路径上经过的边的数量

在这里插入图片描述
这是一颗可爱的树!

在这里插入图片描述
首先,我们把 0 0 0添加在这条路径的某个地方。然后,为了让利益最大化,我们要让 1 1 1 0 0 0连续(即有公共点), 2 2 2要与刚才 01 01 01这段路径连续……最终,形成了上面的图。

可以发现—— 32014 32014 32014……这是一个单谷序列

所以,我们只能在这条路径的两端放 l e n − 1 len-1 len1

假设在靠近 u u u的那一端放了 l e n − 1 len-1 len1,那么状态就变成了 d p x , v dp_{x,v} dpx,v;放在另一端同理。

在这里插入图片描述
定义 f u , v f_{u,v} fu,v表示在 u u u为根时 v v v的父亲, s i z e u , v size_{u,v} sizeu,v表示 u u u为根时 v v v的子树大小。

于是,我们可以发现,有 s i z e u , v × s i z e v , u size_{u,v}×size_{v,u} sizeu,v×sizev,u条路径的 m e x mex mex达到了 l e n len len,所以要加上这么多个 1 1 1

即,下图中以红颜色为一端,以蓝颜色为另一端的路径满足了要求:

在这里插入图片描述
于是,我们得到了状态转移式:

dp[x][y]=max(dp[x][f[x][y]],DP[y][f[y][x]])+size[x][y]*size[y][x];

记忆化搜索即可。

另外, f f f s i z e size size数组可以 O ( n 2 ) O(n^2) O(n2)求出。

总时间复杂度为 O ( n 2 ) O(n^2) O(n2)

真的是神仙题啊

CF1238F(自己做出来的)

首先,挖掘一个性质: 满足要求的子树一定是个毛毛虫(我也不知道怎么形容,于是学了题解中一个人的说法)。即,在这个子树中存在一条链,使得所有节点到这条链的距离均不超过 1 1 1。现在,我们要最大化一个数中子毛毛虫的大小。

显然,我们可以类比 d p dp dp求树的直径的求法,搬到这里来。

时间复杂度 O ( n ) O(n) O(n)

猜你喜欢

转载自blog.csdn.net/Cherrt/article/details/109231552
今日推荐