做题笔记 1
-
\(\color{#52C41A}\texttt{CF627B Factory Repairs:}\)【线段树】发现修改时增加的值一定为正数,所以如果增加到超过 \(a,b\) 就直接替换,用两个线段树维护对于 \(a,b\) 的区间和即可。
-
\(\color{#52C41A}\texttt{CF91B Queue:}\)【线段树】先离散化,用线段树维护权值区间的最大下标,记得开 \(4\) 倍空间。
-
\(\color{#52C41A}\texttt{*CF914D Bash and a Tough Math Puzzle:}\)题目就相当于【线段树】【剪枝】求 \([l,r]\) 中不整除 \(x\) 的个数,如果大于 \(1\) 则是
NO
,否则是YES
。考虑用线段树维护 \(\gcd\),区间修改直接暴力修改,如果碰到 \(x\mid t_k\) 的就不再修改,并加上一个剪枝:如果当前不整除 \(x\) 的个数已经大于 \(1\) 了,就直接return
。记得把cin
换成scanf
。 -
\(\color{#3498DB}\texttt{CF438D The Child and Sequence:}\)【线段树】用线段树维护区间和和区间 \(\max\),单点修改和区间和查询简单,区间取模就暴力修改,如果碰到一个区间的 \(\max\) 小于 \(x\) 就不再修改。
-
\(\color{#9D3DCF}\texttt{*CF510D Fox And Jumping:}\)【01背包】【map】题目等价于求选出 \(\gcd=1\) 的数的最小代价,考虑用
01
背包,但数组空间不够,由于很多位置可能没有用到,可以直接用map
来节省空间。 -
\(\color{#9D3DCF}\texttt{*P4997 不围棋:}\)【模拟】不妨将 “气” 的定义变成所有棋子周边
.
个数之和,这样直接模拟即可。 -
\(\color{#52C41A}\texttt{P1558 色板游戏:}\)【线段树】【状压】发现颜色数 \(\le 30\),考虑直接在线段树上记录每个区间颜色的状况:有颜色 \(x\) 的格子 \(t_k\) 的二进制表示下第 \(x\) 位就为一,合并则是通过按位或。由于
1<<1=2
,所以一开始的初值应该是 \(2\)。 -
\(\color{#3498DB}\texttt{P1967 货车运输:}\)【LCA】【最小生成树】要求两点之间路径上边的最小值的最大值,可以用
LCA
。由于这不是树,于是先用kruskal
求一颗最大生成树,然后在dfs
记录anc
与anc
的路径上边的最小值,记得如果两点不连通就输出-1
。 -
\(\color{#3498DB}\texttt{*P3398 仓鼠找 sugar:}\)【LCA】如果 \(lca(a,b)=lca(c,d)\) 则一定会相遇,又发现只要 \(lca(a,b)\) 在 \(c,d\) 路径上或 \(lca(c,d)\) 在 \(a,b\) 路线上便可相遇,问题变成了判断 \(x\) 是否在 \(y,z\) 路径上。这里需要用到一个性质:若 \(x\) 在 \(y,z\) 路径上,则 \(dis_{x,y}+dis_{x,z}=dis_{y,z}\),用这个判断即可。
-
\(\color{#3498DB}\texttt{*ABC258D Triangle:}\)【bitset】暴力枚举 \(i,j,k\),复杂度为 \(O(n^3)\),用
bitset
来存储 \(s_{i,j}\),依次枚举 \(i,j\),统计与它们都相连的点(\(s_i\&s_j\) 中仍为 \(1\) 的点)的个数,这一点用bitset
的count
函数来优化,时间复杂度为 \(O(n^2\frac{n}{w})\)。 -
\(\color{#52C41A}\texttt{*CF877D Olya and Energy Drinks:}\)【bfs】【剪枝】基础的
bfs
会TLE
,加一个剪枝:如果在结点入队时发现它等于终点,那么直接输出即可,这样可以节省下一次循环的时间。 -
\(\color{#3498DB}\texttt{*P3469 BLO-Blockade:}\)【割点】【tarjan】如果一个点不是割点,那么答案显然就是 \(2\times (n-1)\)(应直接赋值);否则,若删去这个割点,则图会分为几个连通块,每个连通块对答案的贡献为 \(siz\times (n-siz)\),其中 \(dfn\) 小于此点的连通块 \(siz\) 可以在遍历时顺便求出,上方的那个连通块的大小需要计算:\(n-\sum siz-1\)。
-
\(\color{#9D3DCF}\texttt{*SP2878 FKnights of the Round Table:}\)【tarjan】【二分图】为方便先建补图,一个会议其实就是一个奇环。根据点双的性质,在一个点双中,但凡有一个奇环,所有的点都在一个奇环上,所以先把每个点双求出来,判断是/否有奇环就看其不是/是二分图(黑白染色)。多测要清空。
-
\(\color{#52C41A}\texttt{P4667 Switch the Lamp On:}\)【01bfs】对每个点进行
01bfs
:对于每个点,可以走向左上、右上、左下、右下,分别枚举对应的电子元件看是否需要转动。因为是对点进行操作,所以 \(n,m\) 在输入后都得先加一。 -
\(\color{#3498DB}\texttt{*CF1006F Xor-Paths:}\)【折半搜索】暴力枚举时间复杂度是 \(O(2^{n+m})\),会超时,由于 \(n+m\) 只有 \(40\),考虑折半搜索。以左下到右上的对角线为分界(也就是 \(x+y=\frac{n+m}{2}+1\),两个
dfs
分别从 \((1,1),(n,m)\) 出发,第一个用 \(p_{i,j,s}\) 表示到 \(x,y\) 异或和为 \(s\) 的路径数,第二个则调用其累加答案 \(p_{x,y,s\oplus k}\),注意对角线上的格子只能算一次。 -
\(\color{#3498DB}\texttt{*CF1038D Slime:}\)【分类讨论】记 \(s=\sum_{i=1}^n\left\vert a_i\right\vert\),并将 \(a\) 从小到大排序。若 \(a\) 全为正,则以 \(a_1\) 减去 \(a_2,a_3...a_{n-1}\),再用 \(a_n\) 减去 \(a_1\),化简得:\(s-2a_1\);若 \(a\) 全为负,则用 \(a_n\) 减去除 \(a_1,a_2...a_{n-1}\),化简得:\(s+2a_n\);若 \(a\) 有正有负,就先把 \(a_1\) 减去正的 \(a\) 得 \(s'\),\(a_n\) 减去所有负的 \(a\) 得 \(s''\),再用 \(s''-s'\),化简得:\(s\)。要特判一下 \(n=1\) 的情况。
-
\(\color{#3498DB}\texttt{*P4281 紧急集合:}\)【LCA】先求出 \(lca(x,y),lca(y,x),lca(x,z)\),易得这三个点中有且仅有两个点是相同的,最佳集合地点就是与众不同的那一点 \(res\),求出后直接算 \(x,y,z\) 与 目标点的距离即可。
-
\(\color{#3498DB}\texttt{P2860 Redundant Paths G:}\)【边双连通分量分量】【tarjan】【缩点】一个边双连通分量肯定是满足题目条件的,就不用管它了,把它看作一个点,这样把每个边双连通分量都缩成点后,整幅图就变成了一棵树,则答案是 \(\left\lceil\dfrac{\text{这棵树的叶子节点个数(边为 1)}}{2}\right\rceil\)。
-
\(\color{#3498DB}\texttt{P3567 KUR-Couriers:}\)【可持久化线段树】用可持久化线段树来做,维护 \(n\) 棵表示 \([1,i]\) 范围内的权值线段树,对于出现次数严格大于一半这一要求,查询时额外记录一个区间个数 \(len\),如果左儿子大于 \(len/2\) 则调用左儿子,若右儿子大于则调用右儿子,否则直接返回 \(0\)。输入记得优化。
-
\(\color{#3498DB}\texttt{*CF383C Propagating tree:}\)【树状数组】【差分】首先把树形转化为区间,可以想到
dfs
序,而看到区间修改、单点查询,考虑用树状数组维护差分数组。如果改变的是深度为奇数的点,就将差分数组加 \(v\),否则就减 \(v\),相当于维护奇数层和偶数层的差。查询的时候也分深度奇偶性,如果是奇数就加上 \(1-x\) 的差分和,否则减去。 -
\(\color{#3498DB}\texttt{P2724 联系 Contact:}\)【map】先创建一个结构体包括字符串本身、出现次数,用
map
记录每个长度在 \(A\) 到 \(B\) 之间的字符串的编号 \(ts\),对应存在结构体中。最后结构体排个序就行了,注意输出格式。 -
\(\color{#9D3DCF}\texttt{*P2572 序列操作:}\)【线段树】用两个标记分别维护推平、取反,注意推平时要清空取反数组,
pushdown
时是先推平、后取反,如果不是单标记的写法,一定注意可能同时存在推平与取反标记。 -
\(\color{#9D3DCF}\texttt{*CF690A3 Collective Mindsets (hard):}\)【数学】要想一定有一个人猜中的话,那么这 \(n\) 个人必须对某个量分别猜测 \(1\) 到 \(n\) 的每一个数,不难想到 \(\%n+1\)。如果单单是猜一个人的话是无法猜出来的,往总体的方向去想,对于编号为 \(i\) 的人,猜测所有人头顶的数模 \(n\) 余 \(i\),并用看到的所有数字之和来求出自己即可。
-
\(\color{#3498DB}\texttt{*CF690A2 Collective Mindsets (medium):}\)和
easy
【数学】不同的是,海盗只要能存活下来可以不拿金币。显然\(n=1,2\) 时不用金币就可以存活;\(n=3\) 所以得给 \(2/3\) 一个金币,因为 \(2,3\) 即使投他也能存活下来,;\(n=4\) 可以没有金币因为 \(2\) 一定会投他;\(n=5\) 时得两个金币:给 \(1/2/3\) 中的两个人;\(n=6\) 时得一个金币:\(5\) 会投,给 \(1/2/3\) 中的一个人……以此类推,\(n\) 为奇数,\(ans = \left\lfloor\frac{n}{2}\right\rfloor\);\(n\) 为偶数时,\(ans = (n-2^{\left\lfloor\log n\right\rfloor})\div2\)。 -
\(\color{#3498DB}\texttt{*CF1775E The Human Equation:}\)【差分】把 \(b\) 看作 \(a\) 的差分数组,每一次操作就相当于在 \(b\) 上 \(+1/-1\),由于 \(a\) 全为 \(0\) 的充要条件为 \(b\) 全为 \(0\),所以答案为 \(b\) 数组中的极差(记得处理只有正或只有负的情况)
-
\(\color{#52C41A}\texttt{P5248 快速多项式变换(FPT):}\)【进制】【数学】关键是发现其实 \(f(m)\) 就是个 \(m\) 进制数,直接分解即可。
-
\(\color{#9D3DCF}\texttt{*P4801: 饥饿的狐狸}\)【贪心】【排序】先把数组排个序。最大值:左右左右地跳,每次和喝不喝水比较一下,记得从前往后和从后往前的取 \(\max\);最小值:记 \(a_t<W<a_{t+1}\),若 \(t=0\),\(ans=a_n-W\),若 \(t=n\),\(ans=W-a_1\),否则先从 \(a_t\) 往前吃,再喝口水,从 \(a_{t+1}\) 往后吃,\(ans\) 化简完为 \(a_n-a_1\)。
-
\(\color{#52C41A}\texttt{P4868 Preprefix sum:}\)【树状数组】\(ss_i=\sum_{i=1}^k\sum_{j=1}^ia_j=\sum_{i=1}^k(k-i+1)a_i=(k+1)\sum_{i=1}^ka_i-\sum_{i=1}^ki\times a_i\),直接维护 \(a_i\) 和 \(a_i\times i\) 的树状数组即可。
-
\(\color{#52C41A}\texttt{P1525 关押罪犯:}\)【二分】【二分图】先二分影响值 \(x\),接着二分图染色(忽略 \(\le x\) 的边)判断即可。
-
\(\color{#3498DB}\texttt{P4053 建筑抢修:}\)【贪心】【优先队列】反悔贪心,先按 \(T_2\),遍历 \(1-n\),如果当前修理总时长小于 \(T_2\) 直接加入大根堆,否则如果前面时长最长比当前 \(T_1\) 大则替换。
-
\(\color{#3498DB}\texttt{*CF1147C Thanos Nim:}\)【博弈论】如果最小堆的数量超过 \(n\div 2\) 则 Bob 赢,因为 Alice 第一次会取到最小堆,最小堆的数量变得小于等于 \(n\div 2\),Bob 又可以把最小堆的数量变成超过 \(n\div 2\),以此类推,Alice 每次取时最小堆的数量都会大于 \(n\div 2\),当最小的 \(a_i=1\) 时,Bob 可以一次性把最小堆取完,这时加上 Alice 取的,总的堆数便小于 \(n\div 2\)。否则是 Alice 赢。
-
\(\color{#3498DB}\texttt{P2756 飞行员配对方案问题:}\)【二分图】二分图匹配的板子,用匈牙利算法就能过了,记得处理下编号。
-
\(\color{#9D3DCF}\texttt{*P6124: Binary vs Decimal}\)【位运算】【高精度】注意到若 \(n\) 满足条件,则其所有的后缀都满足条件,那么就从 \(0,1\) 开始按位
bfs
,每次记当前维护为 \(k\),枚举所有位数为 \(len\) 的 \(n\),判断变成 \(k\) 位数是否成立:变成 \(k\) 位数是加上 \(10^k\),其二进制末尾有 \(k\) 个 \(0\),则必须原来的 \(n\) 的 \(len+1\) 到 \(k\) 位均为 \(0\)。高精度可以用python
。 -
\(\color{#3498DB}\texttt{UVA10820 交表:}\)【数论】题目相当于求有多少对 \((x,y)\) 满足 \(1\le x, y\le n\) 且 \(\gcd(x,y)=1\),只有 \((x,y)=(1,1)\) 时 \(x=y\),所以设 \(x>y\),枚举 \(x\),\(ans\) 为 \(\sum_{i=2}^n\varphi(i)\),用线性筛筛出 \(\varphi(i)\),最终的答案为 \(2ans+1\)。
-
\(\color{#52C41A}\texttt{*UVA11181 条件概率:}\)【概率】【DP】记第 \(i\) 个人买东西为 \(E_i\),恰有 \(r\) 人买东西为 \(E\),\(P(E_i|E)=P(E_i\cap E)/P(E)\)。记 \(dp_{i,j}\) 为前 \(i\) 个人买 \(j\) 个东西的概率,\(dp_{0,0}=0\) 且 \(dp_{i,j}=dp_{i-1,j}\times (1-p_i)+dp_{i-1,j-1}\times p_i\),\(P(E)=dp_{n,r}\),对于 \(P(E_i\cap E)\),可以把 \(i\) 丢掉后 \(dp\),最终为 \(dp_{n,r-1}\times p_i\)。
-
\(\color{#52C41A}\texttt{P3258 松鼠的新家:}\)【树上差分】把所有 \(a_i\) 和 \(a_{i+1}\) 做树上差分,这样 \(a_2-a_{n-1}\) 会被算两次,\(a_n\) 也多算了一次,计算完再把 \(a_2-a_n\) 所在节点减 \(1\) 即可。
-
\(\color{#52C41A}\texttt{UVA12034 比赛名次:}\)【DP】【组合数】令 \(f_i\) 为 \(i\) 个人时的情况个数,\(f_i=\sum_{j=1}^if_{i-j}\times C_i^j\),\(C_n^m\) 可以用杨辉三角预处理,由于是多组数据,所以要先把所有 \(f_i\) 算出来。
-
\(\color{#52C41A}\texttt{*ABC102D Equal Cut:}\)【前缀和】【双指针】先统计一下前缀和 \(s_i\),对于断点 \(i,j,k\) 枚举 \(j\),\(i,k\) 分别为 \(a_1-a_{j-1},a_{j+1}-a_n\) 中最“平衡”的点,由于 \(s_i\) 是单调上升的,跑一遍“三指针”即可。
-
\(\color{#3498DB}\texttt{*UVA11021 Tribles:}\)【概率】【DP】令 \(f_i\) 为初始只有一只麻球、前 \(i\) 天所有麻球都死亡的概率,\(f_0=0,f_1=p_0\)。若这只麻球生了 \(j\) 只后代,他们在 \(i-1\) 天全部死亡,由于这些后代的死亡是独立的,所以 \(f_i=\sum_{i=0}^{n-1}p_i\times (f_{i-1})^i\),最终答案为 \((f_m)^k\)。
-
\(\color{#3498DB}\texttt{*UVA1638 杆子的排列:}\)【DP】记 \(dp_{i,j,k}\) 为考虑前 \(i\) 个杆子,从左边可以看到 \(j\) 个杆子、右边可以看到 \(k\) 个杆子的方案数。考虑枚举的杆子高度是从高到低,这样就不用考虑把之前的杆子遮住,那么初始化为 \(dp_{1,1,1}=1\),转移需要考虑放最左边、放最右边、夹在中间:\(dp_{i,j,k}=dp_{i-1,j,k}\times(i-2)+dp_{i-1,j-1,k}+dp_{i-1,j,k-1}\)。
-
\(\color{#9D3DCF}\texttt{*UVA11722 Joining with Friend:}\)【平面几何】【分类讨论】详见这里(题解)。
-
\(\color{#3498DB}\texttt{*P1792 种树:}\)【贪心】【链表】【优先队列】如果直接贪心没有正确性保障,需要添加返回机制:从大到小选 \(x\)(用优先队列),当选了 \(x\) 后,把 \(x\) 左边和右边的数删掉(用链表),并将 \(x\) 的值换成两者之和减其权值,这样如果之后发现选 \(x\) 两边更优,就会选当前的 \(x\),也就相当于把 \(x\) 换成了其左边和其右边。
-
\(\color{#52C41A}\texttt{CF23B Party:}\)【构造】当 \(n\le2\) 时,\(ans=0\);当 \(n>2\) 时,可以构造 \(2\) 个人有 \(n\div2 -1\) 个朋友,\(n-2\) 个人都有 \(n\div2\) 个朋友,那 \(2\) 人和 \(n-2\) 人都是朋友(各 \(n\div2-1\) 个),所以答案为 \(n-2\)。
-
\(\color{#3498DB}\texttt{*AGC058B Adjacent Chmax:}\)【DP】令 \(f_i\) 为前 \(i\) 项 的方案数,对于 \(x\),暴力找到它可能改变的最大区间 \([l,r]\),这个区间的 \(a_j\) 都 \(\le a_x\),而对于每个 \(l\le j\le r\),染成 \(a_x\) 会使它的方案数增加 \(f_{j-1}\)(我变前面不变/我不变前面变),依次累加即可。
-
\(\color{#3498DB}\texttt{*P1365 WJMZBMR打osu!:}\)【数学期望】【DP】令 \(f_i\) 为前 \(i\) 个字符得分的期望,\(cnt\) 为当前的字符以前 \(x\) 的个数的期望。若 \(s_i=x\),则 \(f_i=f_{i-1}+(cnt+1)^2-cnt^2=f_{i-1}+2\times cnt+1,cnt=cnt+1\);若 \(s_i=o\),则 \(f_i=f_{i-1},cnt=0\);若 \(s_i=?\),则 \(f_i=f_{i-1}+(2\times cnt+1)\div2=f_{i-1}+cnt+0.5,cnt=(cnt+1)\div2\)(\(cnt\) 也要更新是因为当前有可能变为 \(cnt+1\) 也有可能变为 \(0\))。
-
\(\color{#3498DB}\texttt{P3620 数据备份:}\)【贪心】【链表】【优先队列】思路同 P1792,不过这题是链,还要注意是取最小值所以 \(a_0,a_n\) 得赋为 \(\infty\)。
-
\(\color{#52C41A}\texttt{P2613 有理数取余:}\)【逆元】【高精度】根据费马小定理知:若 \(p\) 为素数,则 \(a^{p-1}\equiv p(\bmod p)\rightarrow a^{p-1}\equiv 1(\bmod p)\),所以原数就等于 \(a\times b^{p-2}\%p\)。一开始数很大,可以先以字符串输入再取模变小。
-
\(\color{#52C41A}\texttt{P7113 排水系统:}\)【拓扑排序】【高精度】拓扑排序的板子题,高精度可以用
_int128
,注意分数的处理。 -
\(\color{#52C41A}\texttt{P1438 无聊的数列:}\)【差分】【线段树】用线段树维护差分数组,操作一就是把 \(a_l+K\),\(a_{l+1}\) 到 \(a_r\) 加 \(D\),\(a_{r+1}\) 减去 \((r-l)\times D+K\),记得判断一下 \(l+1\) 是否 \(\le r\)、\(r+1\) 是否 \(\le n\)。
-
\(\color{#9D3DCF}\texttt{*CF442C Artem and Array:}\)【贪心】【链表】先贪心一遍:如果一个数左边和右边都比它大,则肯定把它给删掉并累加答案,这个操作可以用链表来完成,遍历到 \(i\) 若 \(i-1\) 符合条件就删 \(i-1\),循环直到不符合条件,这样删完整个序列肯定是一个“倒V”或“斜坡”,易知剩下的数除了最大值和次大值都能加入答案,累加即可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】