十月记录
391.哈密顿路径(hamil)
增量构造,发现当不行时可以将另一部分的末尾调整过来。
392.排列(arrange)
对区间值域连续段求逆,同时维护正排列和逆排列,操作等价与交换两个排列的某两个区间,并做一些加法标记。
393.替天行道
考虑“优秀的拆分”,枚举平方串长度 ,每个 个位置设一个关键点。
对相邻两个关键点计算 LCS
,LCP
,可得贡献。
需要做细致的讨论!!!
394.迷失在天堂(交互题)
考虑对偶图,则为一棵有根二叉树。
操作等价于 rotate
,那我们写出 splay
操作即可。
395.所及最高处
考虑增量。
当前插入 ,根据位置对逆序对的影响分别为 。
则长为 ,逆序对为 的排列数为:
由于 ,考虑对分子加上 。
考虑五边形数定理(在分拆数的求解中经常被使用):
由于 在前 只有 项是非 的,暴力做除法即可。
!!!
396.染色(color)
polya
定理!!!赶快学习!!!
本质不同基环树染色方案数。
polya
定理:将一个置换染色的本质不同方案数:,其中 表示用 种颜色染色后使得置换通过 变换后本质相同的方案数。
- 若 ,表示旋转若干次,那么答案就是 。
如果我们能求出有根树的本质不同染色方案数,再求出基环树上旋转的最小循环节,那么容易计算答案,就是将最小循环节长度的数变为一个数,方案数为这些数对应的染色方案数的乘积,这就变为简单置换的问题了。
对于有根树的计算,考虑 dp
,若点 ,有 个儿子同构,设方案为 (可能有多种同构,每种方案乘起来即可)。
那么就是球 个相同,盒子不同 个,那么方案数就是 。
就做完了。
字符串(string)
不会一点!!!!
397.前缀和(presum)
询问可以转化为区间的所有子区间的笛卡尔树 LCA
的权值的和。
二叉笛卡尔树,比较好维护。
具体地,维护出一个点跳到根,右边的贡献,以及左边的贡献。
询问可以转化为 LCA
左右儿子的贡献,左儿子的贡献,右儿子的贡献,这可以由端点贡献和与 LCA
贡献和差分得出。
时间复杂度 。
398.CF1630
A
首先有 i & (n - i - 1) = 0
,(n-1) & k = k
,0 & p = 0
当 时, 与 配对, 与 配对,剩下两两配对。
当 时,先将 与 配对,得到 ,再将 与 配对,得到 ,最后 与 配对,和正好是 。
B
妙妙。
性质:划分为 段时,在 里的数个数至少要比在外面的多 个。
如果固定了 ,将数看作 ,问题变为是否能将数组划分为恰好 个和 的连续子段,即前缀和序列是否存在一个长度为 且开头元素 且以第 个位置结尾的上升子序列。
考虑到前缀和序列的变化是连续的,所以最长上升子序列的长度一定等于 ,则问题变为判断 内的颜色比在外面的元素至少多 就可以。
将值域排列,尺取即可,即长度满足条件的值域段。
C
对于一个值,只需要记录最左最右出现位置,看成线段。
舍去被完全包含的线段。
剩下线段满足左右端点单调,且端点不交。
考虑按照左端点排序,对于无交的,贡献就是 。
记区间 覆盖了区间 。
显然所有非端点位置都可以染色,而剩下了 共 个端点有些可能无法染色。
观察到一个东西,我们可以选择一个覆盖全集的线段集合 ,使得答案达到 。
注意到上界也是这个,那就做完了。
D
观察到只有 才是有用的。
d定义 表示 会乘上 , 表示 会乘上 。
注意到一次操作后所有 的 的异或和 都会变化。
所以能被实现的 的必要条件是所有 都相等。
考虑构造,先使得 的 先满足,发现后面必然满足,跟那道icpc省赛的题很像。
于是考虑 dp
,设 表示 的最大值,其中 。
容易转移。
E
分成两个部分,一个是本质不同排列方案数,令一个是本质不同方案的价值的和。
枚举旋转 次,令 ,方案数为 。
发现 应满足 ,枚举其因数,算出 ,及其方案数 ,总方案数即为
考虑求联通块数量,即为相邻不相同的位置个数,枚举这两个数 ,由期望线性性。
总方案数为:
意义是,先算剩下来的所有数的排列方案数,乘以可能产生贡献的位置数。
太妙了这个式子,因为球不做区分,所以枚举一个位置,两个球产生贡献,那么剩下的方案数依然是一个多重组合数。
发现上式即为:
故只需求出 。
最后答案即为 。
399.CF2021
D
设 表示第 列左端点为 的最佳答案, 同理。
转移以 为例,第一行即选择后面前缀和的 ,后面的行,就是选择 。
E3
显然在 kruskal
重构树上树形 dp
,记录子树中选择 个的最小代价,转移时只需考虑合并两个子树,如果一个子树中没选,另一个子树中选择,那么贡献需要加上没选子树的关键点大小乘上这条边权。
注意到这个凸的,可并堆合并即可,也可以 multiset
启发式合并。
400.CF1558
A
读不懂题,感觉列个方程就好了。
B
直接 转移就好了。
C
玩一下就能发现 次交换到最大的两个数的方法了。
D
发现只需要找到钦定是 的个数,其他都是 ,就能组合数计算方案数了,假设 个小于 个 ,那么方案数就是 。
直接平衡树维护。
E
E
神题!!!!
维护当前的联通块 ,即当前 内部的点两两可达,且已经访问过,外部的点全都没有访问过。
我们需要证明,可行的扩展策略是:
- 从 中一个点出发,走到一个没有访问过的点,一直走到 停止;
- 从 中一个点出发,走到一个没有访问过的点,走回了一个初始没有访问过的点,但是我在这次之前访问到了,然后走回 ,类似一个 形。
并且证明,任意时刻(某些时刻)已经访问过的点集 两两可达。
假设我们从 中的一个点出发,因为每个点度数 ,所以无法走到下一个点一定是当前权值不够,然后这样又退不回来,所以我们的路径一定不会是这样的。
于是路径一定是上面两种之一。
根据归纳,可证点集 两两可达。
如果当前有两种可行访问路径, ,我走了 再走 可行,一定不会出现走了 后不能走 的,所以扩展顺序任意,每次能扩展就扩展。
可以考虑实现了。
考虑如果 ,那么可以直接经过第二条路径,所以每个点只会遍历一次。
于是时间复杂度 。
实现上有许多细节,具体看 Alex_Wei
老师的题解。
小 G 的 DAG
https://qoj.ac/contest/694/problem/1851
https://www.cnblogs.com/PPLPPL/p/15971191.html
随便乱搜根号重构,看到了这个题。
操作分块。
三个操作都可以做。
水群看到的东西
vuqa,请问物品数 n <= 100,物品重量 w <=100 的完全背包,但是背包大小是 1e9,最大化所选物品的权值,有什么做法?谢谢
先贪心
按照性价比
然后剩下的可以调整
调整就是再做个背包,可以证明调整的容量不大,是 w^2
406.LibreOJ NOI Round #2 不等关系
水的时候见到了这道题。还有树上的加强版。
排列 dp
是容易的。
令 表示恰有 个大于号不满足的情况, 表示钦定 个大于号不满足的情况,剩下随便填,则钦定的位置都是 。
于是计数的问题就变成了将 ,分成若干上升序列的方案数,为 。
则 ,,。
由于可以钦定的位置是固定的,所以考虑序列 dp
做,将容斥系数同步计算,令 表示前 个位置合法方案数。
初值应该是 。
可以分治 ntt
优化。
考虑树上问题,令 表示以 为根的联通块有 个点时,整棵子树容斥系数与方案数乘积的和。
对于 ,讨论:
- 规定 ,则 。
- 当规定 ,钦定联通块在这里断开,。
可能是这样的,不保证对。
【总结】一类树上点对匹配问题
gugugu
Atcoder Grand Contest 018 D Tree and Hamilton Path
407.P11146 「SFMOI Round I」Strange Train Game
高妙线性基题,记录一下。
看成长度为 的二进制数,每次会插入一段连续的 。
我们要维护出线性基每一位是否有值,且对应右端点是怎样的。
从高位往低位模拟,考虑将当前这一位右端点最短的先插入,那么其他相同左端点的区间,都要异或上这一段区间,等价于,这些东西都要放到 再插入。
于是从高位到低位扫描线即可,每次启发式合并。
平面图相关
对于一张平面图 , 为平面图上的边把平面划分的区域个数(注意统计最外层的无限区域),则:
一张平面图是连通的等价于 。
联通块数量为 。
与网格图结合。
- 为 相邻块个数 空腔个数 。
- 为相邻对个数。
- 为染色点个数。
不太懂。
408.树上独立集(tree)
手玩一个样例,观察到,结构是若干长度为偶数的链,若干孤立点。
一个观察,必然是若干祖先后代的二个点,若干孤立点。
一个简单的证明:你就考虑度数 的点连向一个子树的边上的两个端点是怎么选的,发现可以调整断开这条边不劣,好像假了。、。、。、!!!!
看题解怎么证的。
树上最大独立集问题有一个经典的
dp
:记 表示节点 的子树中的最大独立集大小,要求 选或不选。转移为:,。假设我们已经知道了一个权值最小的划分,那么可以通过调整得到新的划分使得权值不变,目的是简化虚树的形态。考虑该划分中任意一个集合形成的虚树,有两种情况。如果根节点 存在于任何一个最大独立集中,即 ,则不存在 的儿子 使得 。此时,将该虚树中的点按照 的不同子树分成多个集合,并将 任意放入一个集合(如果 r 不是虚点),则权值一定不会增大。反之,若 ,则存在 使得 。此时,将虚树中的点按照 的子树分开,将 归入子树 ,权值也不会增大。
树上 dp
,带修改,考虑动态 dp
。
观察转移:,分开轻重儿子,转化为支持一条重链上若干 函数的复合,其中 。
观察一个图像,在平面上考虑,可以发现规律,存在分界点 ,满足 ,,,。
于是每次维护 ,推一个复合的变化即可。
时间复杂度 。
排列计数(perm)
树上背包第二维限制为子树大小且不超过 ,是 的!!
409.兰亭序(preface)
排列 dp
即可,经典题。
410.星晴(star)
将式子拆开 。
整除分块确定下取整的值,二次函数,容易确定极值点,要求快速求出前驱后继。
分块即可。
411.你听得到(listen)
sb 拆式子题。下降幂与普通幂的互相转化,扩域。
412.半岛铁盒(box)
如果区间 长度 ,那么做 work(i,l,r)
对每个 ,就能确定 或 。
考虑随机选择 work(a,b,c)
若干次,取中位数最小的那个 即可,概率可以本地撒点算出,很优。
线性不会。。。
413.树的构造(tree)
sb题,构造扫把就好了。
414.后缀(suffix)
注意到关于某个端点有单调性,dp
转移即可,那么每次就是从一个最长合法区间中取 dp
值最大的过来。
415.子序列(subsequence)
注意到 只有在 ,,这些特殊情况需要考虑其他时候几乎都等价于 。
每种数只会出现一次,且 必然在开头,只有这么几种情况:
- 。
- , 后面加上一个长度为 的下降子序列,注意有 的情况要特殊考虑。
- , 后面加上一个 的长度为 的下降子序列,后面加上 。
没了。
416.游戏(game)
高妙题。妙!!!!!妙!!!!!妙!!!!!
序列先后手博弈取数是一个经典的 trick
,每种数 个是每个人最终必然会取到的,策略对冲,可以证明。
当长度为奇数的类需要特殊考虑中间那个点,以第一份为例,将这些点按照先手取得到的贡献从大到小排序,先手会取奇数位置,后面会取偶数位置,第二份同理。
那么 的背包就有了,按照 从大到小排序,每次枚举第一份放多少,第一份有贡献的点数的奇偶性,第二份有贡献的点数的奇偶性。
注意到,枚举第一份放 个,正常贡献是 ,所以对于 同余的 的贡献是一样的。
这启发我们只考虑余数,但是还有中间点的贡献,中间点会产生贡献的条件是:
可以合并为 。
于是只用考虑余数就能转移了,这部分复杂度是 。
再考虑 的倍数,注意到上界有一点细节,讨论出,若 时,上界为 ,否则,上界为 ,其中 的东西直接在余数部分考虑。
一步妙妙的转化,在余数部分 dp
时,若枚举的 ,那么同步进行一个 的转移,仔细想想这是可行的,那么现在上界都相同了,妙!!!!!
妙!!!!!妙!!!!!妙!!!!!妙!!!!!
问题变为:给定 种物品,第 种有 个,每一个体积为 ,问能不能凑出某个固定大小的背包。
首先, 可以变为 ,就是合并体积相同的物品。
然后,我们没看懂题解的做法。
注意到直接可行性单调队列优化背包就行了,这一部分是 。
学习可并堆,简单理解 slope trick
维护在某个 处的 以及函数每个斜率变化点的集合。具体地,如果函数在 位置斜率增加了 ,就在集合中插入 个 。
- 相加,将 直接相加,斜率变化点集合直接合并。
- 取前缀 / 后缀 ,去掉 或 的部分。
- 求 或最小值位置,处理 部分。
- 平移:维护 变化,斜率变化点在全局打平移标记。
- 翻转:维护 变化,斜率变化点在全局打翻转标记。
二分图最大匹配的必经与可行点边
必经边:端点不在同一个强联通分量中。
可行边:要么这条边已经在求出的匹配中,要么这条边两个端点在同一个强连通分量里。
必经点:只需求出非必经点即可。
从 S
开始,走 cap=1 的
边,走到所有 X 部的点都是答案;从 T 开始,走 cap=0 的边,走到所有 Y
部的点都是答案。
感性理解:首先一个不在匹配的点一定会被走到,这些点都是非必经点。一个最大匹配中的点如果是非必经点,一定可以被一个不在匹配中的点替代掉。从某个不在匹配中的 X
部点出发走非匹配边到 Y 部,如果能走匹配边回来,那么翻转所有匹配边和非匹配边,就能用不在匹配中的那个点代替掉匹配中的 X 部点。
可行点:存在一条可行边或者必经边就是可行点。
418.礼物
可以转化成 。
当 时 ,经过一些放缩,所以 。
当 时,再放缩一下 。
于是 枚举即可。
419.形式化题面
妙妙题。
注意到若干点分到一个团当且仅当出边与自己的集合对于所有团内的点相等。
若干点分到一个“独立集”当且仅当出边集合相等。
自然可以考虑到哈希出边集合,与出边与自己的集合。
划分方案是唯一的。
开个桶统计第一类和第二类哈希的个数即可。
建造军营II
不会,想改。。。
420.P11189 「KDOI-10」水杯降温
太妙了这题!!!好!!!
注意到操作是独立的。
将操作反过来好写,子树减一,链加一。
那么考虑分离操作,找到只使用操作一就合法的充要条件,就是树父亲权值 儿子,且 。
那么现在只需要考虑操作二,注意到链会影响某些点的 ,这是劣的,所以如果一开始不满足父亲权值 儿子,就无解。
但是操作二可以使 变大,这是优的。
所以问题变为,最多的操作二次数,使得仍然满足父亲权值 儿子。
记 表示 子树对应的答案。
显然,其具有单调性,考虑二分。
判定条件是:
- ,需要满足的。
- ,满足可以分配。
- 。
就做完了。
421.P11190 「KDOI-10」反回文串
显然每次选择两个不同的字符先放在一组。
然后调整一下就好了。
422.P11191 「KDOI-10」超级演出
计算出一个点能演出的合法区间,那么询问就是一个二维数点。
转移需要考虑每个 的所有出边。
考虑按照度数分治,度数小的直接跑。
度数大的存下来,在度数小的转移完后,用度数小的对 个度数大的点转移。
时间复杂度 。
423.arc185
arc 真的妙。!
A
只需要关注先手打出最后的牌的时候:
- 如果一个人有 张牌,那么他不会立刻输掉。
- 如果先手打出最后一张牌没输,那么他一定赢。
- 因此,先手出最后一张牌时是否输决定了游戏的结果。
假设 是后手手中的最后一张牌。当先手出最后一张牌时,所出牌上的数字之和为 。因此,我们要考虑的是 是否是 的倍数。
若 是 的倍数,即当 时,考虑后手能否打出除了 之外的牌,他的策略如下:
- 当他有 张牌时,他可以结束这一轮。
- 当他有两张牌时,假设 是先手最后一张牌,那么当后手打出倒数第二张牌时,数字和为 ,这是非 的,所以后手一定可以打出非 牌,让先手输。
当 或 时,先手必胜。
B
一个序列是合法的当且仅当其可以操作为一个极差不超过 的递增序列,(是固定的)。
充分性显然。
操作可以转化为 。
考虑证明必要性,先将序列操作成合法的,然后调整。
归纳当前 满足条件。
若 不满足条件,执行以下操作:
- 恰好存在一个位置 ,操作 。
于是判断序列能否操作为一个极差不超过 的递增序列即可。
那么一个序列能被操作的充要条件是什么?
若 ,必要条件是 。
然后证明充分,容易调整。
E
令答案为 ,容易转移:。
推式子。
于是枚举因子直接算,再枚举因子更新即可。
C
先算 表示 的个数。
算 为 的对数。
那么:
然后,寻找 ,满足存在 ,满足:
- ;
- 。
这样的数量为:
做完了。
D
D
考虑 min-max
容斥。
转化成第一次走到一个子集中的某个点的期望时间。
可以发现,任何包含根的子集答案都是 。
如果一个点的祖先被选了,那么这个点是否被选中是无关紧要的。
假设有 条链有点,且共有 个点无关紧要,首先答案是相同的,考虑系数和:
发现,只有 才对答案有贡献,每一条链只有最底部的点可能被选,只用考虑这些子集。
设 表示到达深度为 的点要走的期望步数,钦定根的深度为 。
有:
对于底部不选的链:
假设 条链被选, 条没被选。
太妙了这一步,和上面都联系上了,对于底部被选的链,底部状态是知道的,往上推,对于没有选的链,推出他由根的转移!!!!
426.钢琴教室(anoko)
gdkoi
题了。
一整个线段联通块都是能走的。
于是区间加,线段树二分联通块最左侧点即可。
427.丰雪千里祥音颂(cristmas)
考虑一条边成为交的条件,对应着唯一一种方案。
给每条路径两个哈希值,分别表示正向反向,区间异或。
取哈希值相同的最大边集合即可。
428.不连续子串(subseq)
思路撞墙了就 bfs
。
dp
套 dp
。
一种思路是外层用 ,内层用“以什么字符结尾”的状态。
另一种思路是,相当于钦定内外层子序列的方案数,要求外层子序列在最左的出现位置统计到,内层在对应外层的最左位置统计到。
很妙的思路。
设 ,则要求 ,内层同理。
设 表示考虑到 且钦定 在 内的方案数,转移枚举 上一个位置 ,考虑 中填入 的方案数。
有限制:
- 对于 ,要求 不能在 中,这是内层的限制;
- 令 为最大的 ,必须存在 使得 在 中。
- 对于 中相邻两个数 ,要求 。
做完了。
429.复读机(repeat)
场上做法不能扩展,太不牛了。
考虑二分答案 ,将 的称为小数,反之为大数。
那么最优情况是小数全选,对于每相邻两个小数,如果它们之间最小的大数可选
就选上。
考虑先预处理出来,按值域从小往大扫描线加数,求出若干四元组 表示在 时, 为相邻的小数且有 的贡献,对矩形差分一下,注意 跨过端点时的贡献。
对这些四元组以及询问进行整体二分即可,两只 。
还能做到一只 。
430.小 ω 的距离(dis)
注意到是一棵树高为 的树。
431.小 ω 的匹配(match)
考虑枚举一个左部点选择顺序,从前往后考虑每个左部点,每次选择对于这个点最大的没被考虑到的右部点。
我们声称这样能考虑到所有方案,首先显然是合法,可以构造的。
我的大脑里存在一个归纳调整法,不写了,大概是从后往前考虑,若不是最大的,就调整。
432.小 ω 的树(tree)
考虑拆括号,贡献式子的含义是每个点集恰好选择一个点的权值出来造成贡献。
每个点四种状态,钦定是不是 LCA
,是否造成贡献。
树形 dp
,记录一下子树内没有匹配的点(即没被选的不是 LCA
的点)的个数即可。
433.小 ω 的画作(paint)
不太会的题。
考察一个给定的网格,刻画其合法性。我们断言,合法当且仅当按照行 size 排序之后,下包含上。
考察一个给定的合法网格,刻画其代价。注意到这等价于我们给出一个行列的排列,而当且仅当两行(列)完全相同的时候,它们的顺序是不固定的。特殊处理满行和空列,即可完成计数。
然后分类讨论即可。
434.CF2022
435.CF2025
436.CF2030
D
发现只有 这样才会断开一些东西,每一段要求值域连续且固定,st
表检查即可。
set
维护合法连续段个数。
E
在值域上考虑,每个数的贡献是前缀 ,容易设计 dp
并优化。
F
合法条件等价于每种颜色最左最右看作线段,线段两两不交。
注意到单调性,双指针维护,右端点加入时,树状数组维护相交线段数量即可。
437.CF2023
A
奇妙题。
B
注意到题目相当于求走到一个点的最小跳跃代价 ,贡献为 。
可以从前往后线段树 dp
,分析得这个转移顺序是对的。
也可以发现这相当于一个最短路。
C
复习一下这个理论。
的路径 同余,。
加边时,我们需要判断带来的新环的合法性,注意到判断小环是充要的。
将条件写出来就能做了。
D
gu
438.[YDRG#008 Div. 1] YDSP-S 组赛前模拟 · 云斗杯十月 Golden Round
A
猜个结论就过了。
B
注意到跳 之后不能跳 ,所以操作可以变为 、、。
设 表示当前在 ,上一步在 ,要么操作 ,要么操作 之类的东西,因为这个 可以缩起来看,是单一的。
这样就有 了。
优化不会。。
C
经典线段树记录子树交换状态。
D
注意到答案就是费用流增广两次的结果。
但是增广一次后,会出现负权边,考虑用势能变换边权。
发现这样就没有负权边了,且最短路上边权都是 。
妙啊。
gu。
439.【MX-S4】梦熊 CSP-S 2024 模拟赛
A
随便做。
B
这种拆 的套路要记一下,用两种方向的最优解取 。
先正常求一个最大的联通块,若有 列满足是 但是我取了 ,若 ,则贡献要减去 ,否则减去 。
考虑将算出的贡献直接减去 。
然后再算少考虑的贡献,就是 没有任何贡献的情况,那么钦定若一列是 ,那么必须全部取即可,因为我一定能取。
C
注意到若求出后手能操作的最左最右点,先手如果不能同时覆盖这两个点,就后手必胜。
否则能覆盖,若先手不能多次覆盖全集,也是后手必胜。
否则能覆盖全集,那么先手必胜,因为先手能同时覆盖这两个点,那么所有后手能覆盖的区间,先手都能覆盖。
线段树简单维护即可。
D
没看。
440.Public NOIP Round #7 (Div. 1, 提高)
A
简单题。
B
推推式子就好了。
首先将 同余的数,取出,不同类的是没有限制的。
进一步考虑容斥。
钦定有几个相邻不满足,那么就能知道总段数,将这些段做插入,用组合数搞搞就好了。
注意,需要处理每种情况的大小 的段数信息,做个背包即可。
C
妙妙题。
有结论:
对于 ,令点集 为 必须经过的点。
- 若 非空,那么删去 得到若干联通块,等价类数量就是大小 的联通块个数;
- 否则 是空集,那么等价类数量要么是 ,要么是 ,当且仅当存在点 ,满足存在两个大小 的子树以及一个大小 的子树时,等价类数量为 。
第一部分做扫描线,并查集维护联通块,线段树维护 即可。
剩下的,处理出子树大小次大和第三大也能简单计算。
D
妙妙的结论题。
由特殊性质可以知道,做了 次操作后,最大 个数都挪到后面了。
考虑区间 的最大 个数已经不在 了,那么恰好剩下的数就是前 小的数就是区间 的和。
算 即可。
441.多边形
三角剖分图。
每次可以选择一条让左右点数尽量平均的对角线,可以证明一定有比较平均的。
然后计算这条对角线两个点出发的最短路,那么左右两两的最短路和可以二维偏序求出。
然后分治下去即可,注意,比如分治左部分的时候,最短路可能经过对角线左边点,到达右边部分,发现此时一定经过对角线两个端点,所以将对角线的边权修改为当前全局的最短路即可。
442.[AGC061C] First Come First Serve
拆三维 dp
成两维并且可以互相转移真是太牛了!
dp
做法。
问题相当于,从前往后考虑如果一个点选择左,就没影响,否则需要 中有点被选择。
朴素 dp
需要考虑前面最大的已选端点,以及之前为后面钦定的最紧的需要满足的条件,所以只能三维都记录下来。
竟然可以拆开互相转移?!!?!
设 表示最大已选点为 ,后面无限制的方案数, 表示钦定后面有 的点的方案数。
通过一些观察列出转移后,线段树优化即可。
容斥做法。
观察到不交,真是太牛了。
443.[ARC184B] 123 Set
考虑对每个不是 倍数且不是 倍数的数构造一个矩阵。
1 3 9 27
2 6 18 54
4 12 36 108
行数为 ,列数为 。
每个这样的东西显然是独立的,每次操作就是选择一个数,可以加入他右边与下边的数。
轮廓线 dp
即可。
每个 相同的表都是相同的答案。
需要阅读的:https://www.cnblogs.com/Cry-For-theMoon/p/17629760.html
444.[ARC183B] Near Assignment
妙妙题。
考虑时间倒流。
最后选择可以操作的相同的,操作出一个 *
,可以发现,用这个 *
可以实现任意交换相邻的数。
于是将 B
中相同的数操作到一起,剩下一个,其他都变成 *
,那么每个字符剩下的这个是必要的,而我们的构造实现了这个充分性。
问题就简单了。
445.CF2027
446.CF2035
447.CF2026
448.关于一类求前 k 优解的问题 阅读
算法是堆贪心。
对于每个局面,有 个转移,满足单调性与转移路径唯一性(外向树)。
给出一个多重集 ,全部由整数构成,求它的前 小子集的大小(大小定义为元素的和)。
QOJ7132
首先负数全部取上,然后取反。
将数组从小到大排序,记录状态为 ,分别表示和以及子集的最大下标,则他的转移是 和 。
容易证明不重且单调,太妙了。
只用证明上面两个条件就行了,取出第 小后第 小的一定在堆里。
给出 个正整数数组,定义一种方案是从每个数组里选恰好一个,其代价为选出的所有数之和。求前 优秀方案的代价。其中 。
妙妙题。
考虑每次转移 或 且钦定 后面都选的 。
但是这样每个 会有多个前驱。
不能评价的好题。
「CCO 2020」购物计划 谷着。
449.P11234 [CSP-S 2024] 擂台游戏
不能评价的好题。
场上写了 。
发现每个点只需存大小为 的数组,卡卡常有 ,两个 。
不会一个 。
upd:现在会了,首先可行性的可以压成一个整形。
关键是能到根每种权值的求和中,我需要知道擂主时刻 的和,发现这是不必要的。
首先不满足条件一的都不能贡献到根,所以我们修改节点状态,表示满足条件一,且能到根的擂主和,注意,不修改可行性的状态, 于是也可以方便地知道 ,太妙了!!
预处理出擂主到父亲的边称为关键边。
维护每个点的胜利集合不是很有前途,考虑加入一个点时,判断自己能否成为答案,以及自己能叉掉哪些人,因为每个人能胜利的前提是自己是擂主时 ,且自己不是擂主时,另一个人会输。
性质 : 类作为擂主对 类不影响。
性质 :只考虑若干个 类比赛时,获胜者唯一且确定。
性质 :在比赛总轮次不变时,如果我们按编号从小到大加入 A 类,那么一个人如果在某时刻不能成为冠军,则之后也不能。
性质 :当一个包含目前修改点的胜利集合有 类时,可以直接停止。
性质 :当一个点到父亲边不是关键边时,可以直接停止,结合性质 可以证明。
实现时,无需特判性质 ,一个点往上跳一定满足无 类。
综合以上,复杂度就是 。
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx")
//#pragma GCC optimize("Ofast,fast-math")
//#pragma GCC target("avx,avx2")
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
//#define int long long
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef double db;
#define F(i, a, b) for(int i = a; i <= (b); ++i)
#define F2(i, a, b) for(int i = a; i < (b); ++i)
#define dF(i, a, b) for(int i = a; i >= (b); --i)
template<typename T> void debug(string s, T x) {
cerr << "[" << s << "] = [" << x << "]\n";
}
template<typename T, typename... Args> void debug(string s, T x, Args... args) {
for (int i = 0, b = 0; i < (int)s.size(); i++) if (s[i] == '(' || s[i] == '{') b++;
else if (s[i] == ')' || s[i] == '}') b--;
else if (s[i] == ',' && b == 0) {
cerr << "[" << s.substr(0, i) << "] = [" << x << "] | ";
debug(s.substr(s.find_first_not_of(' ', i + 1)), args...);
break;
}
}
#ifdef ONLINE_JUDGE
#define Debug(...)
#else
#define Debug(...) debug(#__VA_ARGS__, __VA_ARGS__)
#endif
#define pb push_back
#define fi first
#define se second
#define Mry fprintf(stderr, "%.3lf MB\n", (&Med - &Mbe) / 1048576.0)
#define Try cerr << 1e3 * clock() / CLOCKS_PER_SEC << " ms\n";
typedef long long ll;
// namespace Fread {const int SIZE = 1 << 17; char buf[SIZE], *S, *T; inline char getchar() {if (S == T) {T = (S = buf) + fread(buf, 1, SIZE, stdin); if (S == T) return '\n';} return *S++;}}
// namespace Fwrite {const int SIZE = 1 << 17; char buf[SIZE], *S = buf, *T = buf + SIZE; inline void flush() {fwrite(buf, 1, S - buf, stdout), S = buf;} inline void putchar(char c) {*S++ = c;if (S == T) flush();} struct NTR {~NTR() {flush();}} ztr;}
// #ifdef ONLINE_JUDGE
// #define getchar Fread::getchar
// #define putchar Fwrite::putchar
// #endif
inline int ri() {
int x = 0;
bool t = 0;
char c = getchar();
while (c < '0' || c > '9') t |= c == '-', c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return t ? -x : x;
}
inline void wi(int x) {
if (x < 0) {
putchar('-'), x = -x;
}
if (x > 9) wi(x / 10);
putchar(x % 10 + 48);
}
inline void wi(int x, char s) {
wi(x), putchar(s);
}
bool Mbe;
// mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3f;
const int _ = 2e5 + 5;
int n, m, a[_], B[_], c[_], X[4];
int M, mk, g[_ * 3];
char tg[_ * 3]; bool flg[_ * 3];
ll ans[_], cur, w[_ * 3];
int mn[_ * 3], zk;
void dfs1(int o, int dep, int lst) {
if(dep == 0) {
mn[o] = lst;
return;
}
dfs1(o << 1, dep - 1, g[o] == 0 ? max(lst, dep) : lst);
dfs1(o << 1 | 1, dep - 1, g[o] == 1 ? max(lst, dep) : lst);
}
void dfs2(int o, int dep) {
if(dep < 0) return;
tg[o] = -1;
dfs2(o << 1, dep - 1), dfs2(o << 1 | 1, dep - 1);
}
void work(int o, int dep) {
if(dep == zk) return;
if(tg[o] == 0) return; // 非关键边
if(tg[o] == 1) {
if(~o & 1) { // 左
if(a[w[o]] <= dep) {
tg[o | 1] = 2; // 右边保送
if(!flg[o]) cur -= w[o]; // 唯一胜者没有删,删掉
} else { // 左边唯一的点上来了
if(!flg[o | 1]) cur -= w[o | 1]; // 右边被堵上了
dfs2(o | 1, dep); // 右子树所有点没有任何用,打上标记,后面不跑它们
w[o >> 1] = w[o]; // 点上去
flg[o >> 1] = flg[o]; // flg上去
work(o >> 1, dep + 1);
}
} else {
if(a[w[o]] <= dep) { // 右 擂主失败
// 左边保送
w[o >> 1] = w[o ^ 1];
flg[o >> 1] = flg[o ^ 1];
work(o >> 1, dep + 1);
} else {
if(!flg[o ^ 1]) cur -= w[o ^ 1]; // 这个唯一上来的点是否被删掉
w[o >> 1] = w[o];
flg[o >> 1] = flg[o];
work(o >> 1, dep + 1);
}
}
}
if(tg[o] == 2) {
w[o >> 1] = w[o];
flg[o >> 1] = flg[o];
work(o >> 1, dep + 1);
}
}
void solve() {
int k = 0;
ans[1] = 1;
cur = 1;
F(i, 2, n) {
if((1 << k) < i) {
k++;
zk = k;
dfs1(1 << (mk - k), k, 0); // 预处理出 mn
cur += w[(1 << (mk - k + 1)) + 1]; // 算上扩展多出来的子树答案
work(1 << (mk - k + 1), k - 1); // 从原来的根往上跳
}
zk = k;
if(mn[M + i - 1] > a[i] && ~tg[M + i - 1]) cur -= i, flg[M + i - 1] = 1; // 已删除,
work(M + i - 1, 0); // 修改了这个点,那就往上跳
ans[i] = cur;
}
ll Ans = 0;
F(i, 1, m) {
Ans ^= (1ll * i * ans[c[i]]);
}
printf("%lld\n", Ans);
}
bool Med;
signed main() {
// Mry;
// freopen("arena7.in", "r", stdin);
n = ri(), m = ri();
F(i, 1, n) B[i] = ri();
F(i, 1, m) c[i] = ri();
int k = 1;
while((1 << k) < n) k++;
M = 1 << k;
F(i, 1, k) {
char c = getchar();
M >>= 1;
F(j, 1, (1 << (k - i))) {
while(c != '0' && c != '1') c = getchar();
g[M + j - 1] = c - '0';
c = getchar();
}
}
M = 1 << k, mk = k;
int T = ri();
while(T--) {
X[0] = ri(), X[1] = ri(), X[2] = ri(), X[3] = ri();
F(i, 1, n) a[i] = B[i] ^ X[i % 4];
Try;
F(i, 1, M + M) flg[i] = 0;
F(i, 1, M) w[M + i - 1] = i;
dF(i, mk - 1, 0) {
F(j, 1, (1 << i)) {
int o = (1 << i) + j - 1;
if(g[o] == 0) tg[o << 1] = 1, tg[o << 1 | 1] = 0;
else tg[o << 1] = 0, tg[o << 1 | 1] = 1;
w[o] = w[o << 1] + w[o << 1 | 1];
}
}
solve();
Try;
}
// Try;
return 0;
}
450.CF1810G The Maximum Prefix
hot。
如果正向考虑的话,新的前缀和与前面的前缀和有关,说明要记录上一个前缀和与最大的前缀和,不可性。
反向考虑,记录当前最大前缀和 ,从 的最大前缀和转移到 的最大前缀和时,我们贪心地判断 是否属于最大前缀和,即 。
设 表示考虑 ,最大前缀和为 。
但是我们还要求每个长度的答案,直接做是 的。
将初值叠在一起似乎不太行。
注意到我们每次 dp
的转移都是固定的,只是初值不同,因此一个 对答案的贡献也是固定的,我们可以考虑反推贡献系数。
那么初值为 。
就做完了,。
451.七管荧光灯
妙妙题。
考虑博弈论有结论一题的做题思路:找到一种描述必胜必败态的方式。
然后证明钦定必胜态一定能转移到钦定必败态,钦定必败态只能转移到钦定必胜态,且必败的终止局面满足钦定必败态。
妈的,场上暴力打错了,导致与结论/规律失之交臂,要好好检查!!
结论:先手必败的条件是: 上的数相等, 上的数相等,且 上的数异或和为 。
显然终止状态满足。
考虑证明钦定必胜态一定能转移到钦定必败态,我们取出 号管中最小值所在的
管子,记为 , 号管中最小值所在的管子,记为 ,先将 这些管子放在一
边,剩下的管子全选,然后再选 中任意一个取到异或和最高位的(就是三个数的 游戏),容易证明不会成环,显然可以通过调整这些管子使其到达必败态。
然后证明钦定必败态无法转移到钦定必败态,依然等价于三个数的 游戏,因为上面三个如果选必然全选,下面三个如果选也必然全选,然后变成三个数,发现我们只能取至多一个数,就转化完了,取完后异或和一定非 。
然后数位 dp
即可,可以容斥。
452.KD-TREE
https://oi-wiki.org/ds/kdt/#插入删除
https://www.luogu.com.cn/training/4295#information
https://www.luogu.com.cn/article/frygd6i8
https://zhuanlan.zhihu.com/p/678395006
https://www.cnblogs.com/tzcwk/p/kdtree.html
https://www.cnblogs.com/hztmax0/p/18460729
目前学习了开两棵 kdt
的动态插入。
先暂时存在插入的点,攒了 个插入后,与小树合并,当小树大小超过 后,与大树合并,顺便将小树用所有散点重构,注意合并指重构。
查询需要在两棵 kdt
中查询,以及查看散点。
合并的复杂度为 ,取 ,得到 。
453.异或和(xor)
原题在 cf 上。
考虑将 分别拆成 个形如 的区间,且 后 位都为 。
两个这样的区间做运算,结果还是一个区间,可以快速算出来,现在能做到 。
发现对于两个区间,若 ,运算后后者的后面部分不用考虑,于是只需要在线段树上考虑同一深度的区间,时间复杂度 。
454.仙人掌(cactus)
积累一个东西,用线段树合并做形如 dag
可达点集合这样的东西,每次合并新建点,并加上 if(x==y) return;
的剪枝,不太好卡。
可以看代码。
455.冰风迷途的勇士(blizzard)
乘号最多 次,设 表示值为 ,使用 个乘号,至少多少个加号。
转移考虑 ,乘法合并,加法合并。
乘法合并可以做到 。
对于加法,发现做加法时,其中一个式子的值不超过 ,枚举即可。
456.沉沦之心(heart)
不太理解的题。
457.霍_Space
思考这个东西和线性基的构造很像。
发现 的张成为 的张成的子集时有解。
初始想法是将 变成线性基,扫一遍位数,拿基底去构造那些 ,但是并不好构造,这不是无环的。
思考我们还能做什么?
我们可以做交换两个数,做逆操作。
所以考虑将 也缩成线性基。
显然有解是 的基底包含 的基底。
先交换,让 的基底和 的基底对应,多出来的基底自己消除。
这样再像上面那样扫一遍就能构造了,就是从高到底考虑 的基底,取操作这一位 ,最后如果基底的位置不同的话再操作基底的位置。
458.排列(perm)
妙妙题!!!
最小化操作次数就是 置换环个数。
问题变为这样,给你排列 ,交换两个数 ,代价为 ,求使得 的最小代价,结论为 。
我们希望给出构造,考虑让两个部分都尽量达到下界,所以每次让后者在相同置换环内交换。
将两组对应数,画到数轴上,可以玩出交换后后者还能满足下界的条件。
考虑每次固定一组数为最小的 的组,然后再他的置换环上考虑,发现对于 的置换环,一定能找到合法的第二组数。
复杂度在于找的时间。
发现操作这两组数后,原置换环会分裂成两个置换环,所以可以考虑启发式分裂。
维护两个指针,一个从 开始往左跳,另一个往右跳,当找到合法的 时停止,并操作。
时间复杂度 。
459.癞疙宝走迷宫(maze)
后面再好好想想,类似 TB5
分治。
460.混乱
正解不会!有学的必要!!大概理解了。
考虑线性规划对偶(推的太慢了,要加强!),问题转化为,给每个关键点赋权值 ,使得每个区间包含的关键点 的和 ,目标是 最大。
显然有贪心,扫描线,对于一个关键点 ,将他的权值赋为包含 的区间 的最小值 ,并执行修改:将包含 的区间 ,KDT
优化即可。
正则表达式学习
https://imageslr.github.io/regexone-cn/lesson/conditionals.html
OI 赛制比赛 emergency kit(2024 Winter Edition)
OI 中的小技巧(工具)
https://www.cnblogs.com/caijianhong/p/18183222#%E5%8F%AF%E6%89%A7%E8%A1%8C%E6%96%87%E4%BB%B6
461.超立方体
在看了在看了。
462.西克
是很显然的,重链剖分拆成 条重链,往上跳直接预处理即可,往下跳倍增即可。
瓶颈在后面部分,但是似乎可以从上往下考虑一些可撤销并查集之类的东西计算这部分的贡献,可以优化到一只 。
463.尼特
好题!妙妙题!!
记住题意是你有长度为 n 的答案序列 a,然后随机有一个长度为 n-1 的序列 b,你需要在你的序列中恰好删掉一个使得匹配数量最大。
记住题意是你有长度为 的答案序列 ,然后随机有一个长度为 的序列 ,你需要在你的序列中恰好删掉一个使得匹配数量最大。
怎么说?
考虑一个匹配的过程,维护长度为 的答案序列,表示删掉这个位置后匹配的数量。
那么若 ,表示是 ,若 ,表现是 。
前者可以转化为 ,注意到全局 是一定会贡献到答案里的,是独立的!!,所以可以先提出来算期望!!
那么现在就是有 次机会,每次有 的概率给答案加一,那么答案加的期望值为 。
然后观察到若 ,那么这是无贡献的,所以我们只需考虑 的位置,考虑 还是 还是都不相等。
假设共有 个 的位置,枚举有 个 或 的。
- ,有 的概率,。
- ,有 的概率,。
问题变成,有 的序列,考虑后缀和的最大值,那么我们可以从后往前维护后缀和。
将 看作往上, 看作向右,那么可以可以继续枚举终点,容斥答案 ,那么就是算从 走到终点不经过 的路径数量,反射容斥。
列出式子后,经过复杂的分类讨论,可以优化到线性,或者 –oeis
–。
464.苯为
树的贡献很好考虑。
考虑环,dp
,当前点颜色与起点是否相同,转移可以矩阵优化。
那么一个 的答案只跟 有关,注意到可以维护以 为根所有路径的矩阵积的和,可以做合并,于是就是线性的了。
465.故障机器人(bot)
注意到只需要考虑往上的字符对往右的字符的贡献。
466.反二维偏序(reverse)
题目条件相当于说有交。
考虑双指针,当前 不存在,加入线段 ,只需讨论含 的三元组是否有贡献,讨论 的位置即可。
467.DS?代数!(datamath)
离线下来,扫描线,考虑加入一个数 ,找到左端点对应 的段,会分裂开来,分裂的左端点可以线段树二分得出,操作次数是 的。
我们可以沿用这个做法,在线地处理出若干不交的贡献 表示在时间 , 的值为 ,只有 对。
只用处理 相等的询问和修改,只用主席树,维护当前时刻还存在的 的标记,查询可以考虑维护一个关于查询时间 的一次函数,可以标记永久化。
大概就做完了。
468.mx17
A
似乎一半取 ,一半取 是最优的。
B
妙妙题。
P8162 [JOI 2022 Final] 让我们赢得选举 (Let's Win the Election)
显然所有人一起演讲更优,且一定是先招人再拉票。
考虑按照 从小到大排序,记 为拉票, 为招人, 为演讲。
发现 不可能在 前面,否则交换更优。
那么考虑最后一个 ,他前面只能是 或 ,然后这样还有空余的名额,考虑将剩下的按照 从小到大设为 。
这样就能解释贪心为什么有问题了,有的州 极小,而 也比较靠前,那么可能这个州选择 更优。
考虑 dp
,枚举选择 个 。
从前往后,直接决策每个州选 还是 ,就是不能不选,即决策前面部分,这样每个 的贡献可以直接算。
对于每个 的状态,只需将 按照 排序选出最小的前几个填补空隙即可。
时间复杂度 。
C
注意到 可以转化为 ,其他同理。
考虑将 相同的字符缩成一段。
设 表示考虑前 ,其中 是他的段的末尾,, 还是 。
转移考虑枚举前一段末尾 ,考虑段 ,若存在 ,使得 ,那么 ,其他情况同理。
那么合法的 的一段区间,处理出来,同时前缀和优化一下转移即可。
D
在 nb 的题单里,不讲了。
469.mx16
A
wc,怎么选择了非常难写的做法。
处理出 个区间,每个区间算答案。
差分转成前缀。
其实,直接数位 dp
,设 表示当前考虑到了第几位,更改了 次定义,是否卡着上界,上一位的定义是否和现实左右一样。
B
没有修改,显然的单调队列优化 dp
。
有修改,考虑前预处理前缀后缀 dp
,将中间的 项的 dp
值再跑一遍即可,因为每 个就有一个选择的。
C
妙妙题。
对于一个环,长度为 ,发现如下规律:
- 偶数,。
- 奇数,。
方案是唯一的。
然后每个环显然分配的是一个区间。
考虑合并环长相同的环,记环长为 的有 个,设计 其中 表示集合 ,其中 ,表示环长为 的已经分配了 个,使用了前 袋苹果。
转移枚举下一个环长 ,,可以发现 取值不是很多,转移的 只有 个,可以通过。
D
考虑点分治,根为 ,处理 表示 的危险度,满足 能到 。
表示要使得 能到 ,在 时的最小危险度。
那么就变成统计 在 的不同子树,且 。
在 统计一下,然后容斥掉 子树内的即可。
CF2029
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18442452
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!