杂题记录2

CF53E Dead Ends(状态压缩)

题意

给你 \(n\) 个点和 \(m\) 条边,求这个图的有 \(k\) 个叶子的生成树的个数 (\(n \leq 10\))

solution

\(n\) 特别小,考虑状压,于是状态设计就是 \(dp_{sta1,sta2}\) 表示 \(sta1\) 的点与 \(1\) 联通,其中 \(sta2\) 的点是叶子节点
转移的话就是新加入一条边 \((u,v)\)\(u\) 原来就与 \(1\) 联通 )时,把 \(v\) 加到 \(sta1\)\(sta2\) 里,如果 \(u\) 原来在 \(sta2\) 里就把他除去
但是这样可能会算重,比如对于 \(2-1-3\) 的图,可能是把 \(3\) 加到 \(2-1\) 里,也有可能是把 \(2\) 加到 \(1-3\)
所以我们可以人为钦定一下加叶子的顺序,具体的,如果 \(v\) 是转移后编号最大的叶子才转移
submission

CF70E Information Reform(树形dp)

题意

给你一颗树,你可以花 \(k\) 的代价将一个节点变为区域信息中心,对于每个节点,若它到离他最近的区域信息中心的距离为 \(dis\) 则代价为 \(d_{dis}\)\(d\) 数组单调不降),求最小代价,并输出每个节点选择的最近区域信息中心编号 (\(n \leq 180\)

solution

很显然要 $dp $ ,设 \(dp_{i,j}\) 表示节点 \(i\) 选择 \(j\) 为区域信息中心,子树内代价最小值,转移的话,枚举儿子选的区域信息中心,如果和 \(i\) 选的一样就减去 \(k\) ,初始值就是 \(dp_{i,j}=d_{dis_{i,j}} + k\),转移式子:

$dp_{t,i}=\sum\limits_{to \in son_{t} } min ( dp_{to,j}-(i==j) \times k ) $

submission

CF115E Linear Kingdom Races(线段树优化dp)

题意

\(n\) 条道路,每条道路修缮的代价为 \(w_i\) ,给定 \(m\) 个区间,当你将区间 \([l_i,r_i]\) 的道路都修缮完后会获得 \(v_i\) 的代价,问你最后总代价最大是多少 (\(n,m \leq 2\times 10^5\)

solution

和NOIP2023T4天天爱跑步很像,先考虑朴素 \(dp\) ,设 \(dp_i\) 表示考虑了前 \(i\) 条道路的最大代价,转移就是 \(dp_i={max \{ dp_{j-1}+calc(j,i),dp_{i-1}\}}\) 其中 \(calc(j,i)\) 表示将 \(j\)\(i\) 这一段道路修缮后能满足的区间获得的价值减去修道路需要代价。优化的话,扫描线维护区间获得的代价就行,线段树第 \(i\) 个位置表示 \(dp_{i-1}+calc(i,now)\) 维护区间最小值即可,注意 $dp_i $要和前面的 \(dp_j\)\(max\)

submission

CF258E Little Elephant and Tree) (扫描线)

题意

有一棵根节点为 \(1\) 的有根树,这棵树每个节点都有一个集合,初始为空。

进行 \(m\) 次操作,第 \(i\) 次操作给出 \(a_i\)\(b_i\),把 \(i\) 这个数字分别放入 \(a_i\) 和 b_i$ 这两个点为根的子树里的所有集合中。

最后输出每个点有多少个除它本身的点集合与它的集合有交集

solution

每次相当于把 \([dfn_a,dfn_a+siz_a-1]\)\([dfn_b,dfn_b+siz_b-1]\) 这两个区间互相加入代价(包括他们本身的子树)于是可以扫描线 ,在 \(dfn_x\) 时加入贡献, \(dfn_x+siz_x\) 时减去贡献。但是最后要求有多少不同的点,直接维护比较难搞,于是正难则反维护有多少个点为 \(0\) ,于是维护最小值和最小值的个数即可。

Submission #345994030 - Codeforces

CF285E Positions in Permutations (计数)

题意

给定 \(n\)\(k\) ,求有多少个 \(n\) 的排列 \(p\) 使得 $ |p_i-i|=1$ 的 \(i\) 的个数 恰好\(k\)

solution

因为题目问的是恰好,所以可以考虑求钦定的然后再二项式反演:令 \(g_i\) 表示钦定至少有 \(i\) 个位置满足条件,答案就是 \(\sum\limits_{i=k}^{n} (-1)^{(k-i)} \times \binom{i}{k} \times g_i\) 所以现在考虑怎么求 \(g_i\) 。令$ f_{i,j,0/1,0/1}$ 表示考虑了前 \(i\) 个位置,有 \(j\) 个地方满足条件,且 \(i\)\(i+1\) 分别有没有被选的方案数,简单转移即可,注意\(i=n\) 时 要特判。最后 \(g_i=(f_{n,i,0,0}+f_{n,i,1,0})\times (n-i)!\)

Submission #346014626 - Codeforces

CF383E Vowels (高维前缀和)

题意

有一个由‘a’-'x' 组成的元音集合,但是你不知道有哪些字母在里面,给你 \(n(n\leq 10^4)\) 个由三个字符组成的单词,一个单词合法的条件是里面至少有一个原因字母,问你对于 \(2^{24}\) 种可能的元音集合,有多少个合法的单词数,输出所有答案的平方的异或和

solution

设元音字母集合为 $sta $ 则一个单词不合法当且仅当它的字符集属于 $sta $ 的补集。所以对于补集的子集有多少个数可以用高维前缀和来做,每次枚举一个元素 \(i\) 然后枚举所有集合 \(j\) ,若 \(i \in j\)\(dp_j+=dp_{j \oplus (1<<i)}\) 这样就能求出 \(j\) 的所有子集的和

Submission #346017972 - Codeforces

CF442D Adam and Tree

题意

给你一颗树,你需要给每个边染颜色,使得同一颜色组成的边集是一条路径,点 \(i\) 的权值为它到根(1号点)的路径上的不同颜色数,求所有点权值最大值最小的一种染色方案

solution

咕咕咕

ARC162F Montage

题意

给定 \(n\)\(m\) (\(n,m \leq 400\)) ,求有多少个 \(n\)\(m\) 列的01矩阵满足这个矩阵的每个子矩阵的左下角 $\times $ 右上角 \(\geq\) 左上角\(\times\) 右下角

solution

dfs搞出一些比较小的样例,空行和空列显然是没有必要的,删去后发现每一行的1都是一段区间,且每一行的区间的左右端点都是单调不升的,且每行的区间都至少有公共交点。考虑为什么满足这个条件。首先看为什么 \(1\) 是一段区间。因为如果当前行有一个\(0\) 将一段 \(1\)分开了,说明这一列的上面行或者下面行有一个 \(1\) 然后发现对于这两种情况,都可以组成一个不合法子矩阵,所以 \(1\) 是一段区间,再看为什么 \(l_i,r_i\) 单调不降。如果下面这一行的下一行有 \(1\) 出现在当前行的 \(1\) 的左边,那么一定可以和它上面的\(0\) 和后面的 \(1\)组成一个不合法的矩阵,没有相交点同理。所以就可以 \(dp\) 了, \(f_{i,l,r}\) 表示第 \(i\) 行选择 \([l,r]\)\(1\) 时的方案数。

\(f_{i,l,r}=\sum\limits_{k=l}^{r+1}\sum\limits_{p=r}^{m} f_{i-1,p,k}\)

使用二维前缀和即可

没写。

[P5290 十二省联考 2019] 春节十二响

题意

给你一颗 \(n\) 个点的树,每个点有一个权值,你需要将这些节点分成很多段,每一段不能有祖先-后代关系,每段的代价为段中点的点权最大值,问所有段的代价之和最小为多少

solution

对于每颗子树,它的子树是可以两两合并的,贪心地合并就是从大到小排序后依次合并,于是就可以树上启发式合并来求答案了

记录详情 - 洛谷 | 计算机科学教育新生态

ARC160D Mahjong

题意

给定 \(n,m,k\)\(1\le k\le n \le2000 ,1\le m\le 10^{18}\)) 求有多少个长度为 \(n\) ,和为 \(m\) 的数列 \(A\) 可以通过以下两种操作变成全为 \(0\) ,答案对 \(998244353\) 取模

  • 选一个元素减去 \(k\)
  • 选一个长度为 \(k\) 的子串,子串中每个元素减去 \(1\)

solution

首先 \(m\) 如果不是 \(k\) 的倍数肯定无解。原序列一定是做了若干次操作2然后让每个数都是 \(k\) 的倍数

我们会发现同一个位置以它为起点的子串不会被操作2操作大于等于\(k\)次,因为这样相当于对这\(k\)个位置做了1次操作1。所以我们最多做了\((n-k+1) \times k\)次操作二,两个合法序列本质相同只会是操作一和操作二互相转化,现在钦定每个位置的操作二次数小于 \(k\) 了就可以直接计数了,设 \(b_1\)\(b_{n-k+1}\) 表示每个位置操作二的次数,\(b_{n-k+2}\)\(b_{2*n-k+1}\) 表示每个位置的操作一次数,求的就是满足以下条件的序列 \(b\) 个数

$\sum \limits _{i=1}^{2*n-k+1} b_i=\frac{m}{k} $

$ i \in [1,n-k+1],b_i \le k-1$

使用容斥即可,枚举不满足 $b_i \le k-1 $的个数

Submission #70546556 - AtCoder Regular Contest 160

SDOI2019热闹的聚会与尴尬的聚会

题意

给你一个 \(n\) 个点 \(m\) 条边的无向图( \(n\le 10^4,m \le 10^5\)),你需要选两个点集,一个热闹度为 \(p\) 的点集指选的每个点都至少有 \(p\) 个点直接与它相连,尴尬度为 \(q\) 的点集是一个大小为 \(q\) 的独立集,你需要求出一组方案(输出分别选了哪些点)使得 $\lfloor \frac{n}{p+1} \rfloor \le q 且 \lfloor \frac{n}{q+1} \rfloor \le p $

solution

首先这两个问题应该是分开的,因为移项后就是 \(p\times q+p \ge n 且 p\times q+q\ge n\) ,所以分别求 \(p\)\(q\) 的最大值。第一个问题可以二分,然后每次删掉deg<mid的点就行,或者可以直接贪心做,每次删掉度数最小的点(因为你想要让现在的答案变得更大,就必须要把度数小的点删掉)然后取过程中的最大值。对于第二个问题,直接做疑似挑战图灵奖,我们看能不能做第一问的时候顺带求了。发现我们可以每次加入度数最小的那个点,再删去与它相连的点。每次删点最多只会删掉 \(p\) 个点,不然的话这个点的度数大于 \(p\) 且他的度数最小,那么第一问的答案就不会是 \(p\) 了。所以这样就正好满足了题面的条件

记录详情 - 洛谷 | 计算机科学教育新生态

P5324 BJOI2019删数

题意

定义一次删数操作如下:记当前数列长度为 \(k\) 则删掉数列中所有等于 \(k\) 的数

给定一个长度为 \(n\) 的数列,有 \(q\) 次操作,每次将数列整体加一或整体减一或修改某个位置的值,问修改后将数列删空最少需要修改几个数

solution

思考怎样的数列是能够被删空的,首先数列最大值应为数列长度,最小值大于0,其次相邻大小的两个数的差应该是较大数的出现次数。再来考虑怎样修改是最优的,删掉一个数 \(x\),下一个要删的数就应该是 \(x-cnt_x\) ,如果这个数没有出现过,那么我们就需要找一个数修改了才能继续删,所以我们可以考虑对于数列里每个数覆盖 \([a_i-cnt_{a_i}+1,a_i]\) 这样覆盖后,没有被覆盖的地方就是必须要修改一次才能得到的数,于是答案就是 \([1,n]\) 没有被覆盖到的地方的数量,可以使用区间加和区间减来维护这个东西,数零就是维护最小值以及最小值个数,对于数列整体加和减,就是将区间平移了,用一个变量记录即可,这里还有一个细节,就是一个数如果被平移到了区间右边,那么它的贡献是不能被算进来的

提交记录

CF997E Good Subsegments

题意

给定一个长度为 \(n\) 的排列 \(p\) ,定义一个好区间 \([l,r]\) 使得 \(p_l\)\(p_r\) 出现了从最小值到最大值之间的每个整数,\(q\) 次询问,每次查询 \([l,r]\) 中有多少个好的子区间 (\(1\le n,q \le 1.2\times 10^5\))

solution

这个东西在线不好求,考虑将询问离线下来,因为这是一个排列,所以好区间的要求实际就是 \(max-min=(r-l)\)\(f_l=max-min-r+l=0\) ,于是可以扫描右端点,维护左端点的 \(f\) 值,因为 \(f\ge 0\) 所以可以直接维护最小值以及最小值的个数,对于修改最大值和最小值,使用单调栈就行了。但是它这里询问的是子区间,于是维护历史最小值个数就行了,注意下传历史信息的那个 \(tag\) 时必须要满足条件才下传(即 \(mi_p==mi_{son}\) 才把标记下传给儿子,实际就是等于 \(0\) 时才下传,因为根的最小值一定是 \(0\) ),这一类子区间的问题好像都是维护历史信息

sunmission

[Ynoi Easy Round 2023] TEST_90

题意

给一个长度为 \(n\) 的序列 \(a\)\(q\) 次询问,每次查询 \([l,r]\) 中有多少个子区间出现过的数的个数为奇数。

solution

首先把询问离线下来,然后扫描线直接维护区间内出现了多少个数。题目要求出现个数为奇数的,设 \(f_l\) 表示左端点为 \(l\) 时出现的数的个数,线段书上维护区间内 \(f_l\) 为奇数的个数和为偶数的个数,每次修改时交换一下,因为是求子区间,所以再维护一下历史和就行了(注意这里不能只维护一个 \(tag\) ,要维护奇数被算进答案的 \(tag\) 和偶数被算进答案的 \(tag\),每次也要交换)

CF568E Longest Increasing Subsequence

题意

给定一个长度为 \(n\) 的数列( \(n \le 10^5\) ),其中有 \(k\) 个位置是 \(-1\)\(k\le 10^3\) )表示这个位置为空缺的,你有 \(m\) 个数( \(m\le 10^5\) )每个空位是其中一个数(只能用一次),构造出严格递增子序列最长时的数列

solution

重复填同一个数字对答案不会有多的贡献,所以可以先不管这条限制。 除了常规的数据结构 \(O(N \log N)\)\(LIS\) ,还可以用二分求 \(LIS\) 。具体的,设 \(f_i\) 表示长度为 \(i\)\(LIS\) 的结尾的数的最小值。(未完)

posted @ 2025-10-27 19:14  Xdik  阅读(34)  评论(0)    收藏  举报