2023 年 10 月训练记录
训练记录
10 月了。
CF457F An easy problem about trees#
尝试理解,感谢 cz_xuyixuan 的题解。
算作是很多情况的补充说明。
我们不妨先二分答案,将 的设为 , 的设为 ,于是问题转化为了权值均为 的版本。
我们称一棵树的大小为其非叶节点数。
我们称一棵大小为奇数的树为奇树,大小为偶数的树为偶树。
对于奇树有两棵偶子树的情况:最后一次操作由先手完成。我们称,先手能够在当前子树内获胜当且仅当他能在任意一棵子树作为先手内获胜。这是因为如果先手可以在任意一棵子树内获胜,他就可以采取模仿的策略:先在他能赢的子树内操作,如果后手去操作了别的子树,则先手也同样去另一棵子树操作。反之,后手也可以用同样的策略,使得先手在两棵子树内都无法获胜。
对于奇树有两棵奇子树的情况:注意到一棵子树被操作完后,另一棵子树的先后手会发生变化,所以情况就变得更加复杂了,不能单纯地模仿。我们观察其中一棵子树就会发现操作的形式相当于跳过了一次自己的回合,先后手都有这样的机会。
可以发现的是,多次跳过回合是没有意义的,因为对方玩家同样可能进行跳过,而使我方上次的跳过失效,因此,只需要记录是否可以跳过的回合。
于是我们增设状态 :
- :不能 ;
- :可以 ;
- :先手可以 ,若先手不 ,后手必须 ,详见后文。
于是,我们分情况讨论:
-
:
-
奇树有两棵偶子树:先手能获胜当且仅当在任意一个子树内的 能获胜;
-
奇树有两棵奇子树:先手能获胜当且仅当在任意一个子树内的 能获胜;
-
偶树:显然有一个奇子树和一个偶子树。我们不妨枚举先手的第一步操作:
- 操作奇树,那么对于后手相当于情况 1.1。所以,先手能获胜当且仅当先手能奇树中 获胜,并且后手不能在偶树中 获胜;
- 操作偶树,那么对于后手相当于情况 1.2。所以,先手能获胜当且仅当先手能偶树中 获胜,并且后手不能在奇树中 获胜。
先手可以选择操作。
-
-
:
先手首先可以考虑 ,若后手不能在剩余局面中获胜,则先手获胜。
注:这里我还不会证明若后手不 ,则先手一定会 来获得子树内的最后一次操作的权利。
感性理解下,感觉很有道理。- 偶树:我们声称若后手不 ,则先手一定会 来获得子树内的最后一次操作的权利。那么,先手有如下两种操作:
-
先手如果可以在偶树中 获胜,则先手必胜。这是因为先手可以不停地在偶树中操作,那后手有两种可能:
- 操作了奇树,先手选择 ;
- 了。
上述两种情况都变成了情况 1.1,先手只需要模仿即可。
-
先手如果可以在奇树中 获胜,则先手必胜。这是因为先手可以不停地在奇树中操作,那后手有两种可能:
- 操作了偶树,则先手选择 ;
- 了。
上述两种情况都变成了情况 1.1,先手只需要模仿即可。
不过,先手也可以选择在操作奇树的时候 ,所以是 。
不过有个特例:假设偶树的大小为 ,则后手可以不选择操作偶树,所以,左子树就变成了 的情况。
-
- 奇树有两棵偶子树:我们枚举先手的第一次操作,于是对于后手就变成了 2.1 的局面。
- 奇树有两棵奇子树:我们枚举先手的第一次操作,于是对于后手就变成了 2.1 的局面。
- 偶树:我们声称若后手不 ,则先手一定会 来获得子树内的最后一次操作的权利。那么,先手有如下两种操作:
-
:
基本和 类似。
- 偶树:根据状态定义,双方必定会有一方 ,所以先手一定会获得子树内的最后一次操作的权利。那么,先手有如下两种操作:
-
先手如果可以在偶树中 获胜,则先手必胜。这是因为先手可以不停地在偶树中操作,那后手有两种可能:
- 操作了奇树,先手选择 ;
- 了。
上述两种情况都变成了情况 1.1,先手只需要模仿即可。
-
先手如果可以在奇树中 获胜,则先手必胜。这是因为先手可以不停地在奇树中操作,那后手有两种可能:
- 操作了偶树,则先手选择 ;
- 了。
上述两种情况都变成了情况 1.1,先手只需要模仿即可。
不过,先手也可以选择在操作奇树的时候 ,所以是 。
这种情况不需要分偶树大小为 讨论,因为根据状态定义,若先手不 ,后手必须 。
所以只需要执行 即可。
-
- 奇树有两棵偶子树:我们枚举先手的第一次操作,于是对于后手就变成了 3.1 的局面。
- 奇树有两棵奇子树:我们枚举先手的第一次操作,于是对于后手就变成了 3.1 的局面。
时间复杂度 。
不过,我们可以把状态记成 从而避免二分。
时间复杂度 。
记录。
Ucup2 Stage5 Sets May Be Good#
我们考虑计算 ,这里 表示 集合的导出子图的边数。
我们记 。
我们考虑删掉 号点。
注意到如果 的取值会影响 的奇偶性,则正负相消,贡献为 。
所以我们需要保证下列条件满足:
我们考虑是否存在位置 ,满足 。
-
如果不存在这样的 ,那我们根据 的取值分类讨论:
- ,则贡献乘 ;
- ,贡献变成 。
-
如果存在一个位置 ,满足 。
那么,根据 ,我们可以得出:
我们考虑对于一个序列 计算答案。
于是,我们就可以把 的矩阵,在 的时间内,变成 的矩阵。
注意到 有两种取值,所以贡献要 。注意到上述式子继续展开,则 的项,所以贡献可能 。
总时间复杂度 。
记录。
Ucup2 Stage6 A Digital Nim#
考虑裸暴力:
F(i,1,n){
F(j,1,D(i))if(!f[i-j]){
f[i] = 1;
break;
}
}
那显然,我只关心 最后的 ,记录和当前 的差 ,如果 ,则 ,否则 。
于是不可以不断更新 。
注意到 ,所以 的一个很松的上界是 。因为不可能出来连续 个 。
考虑 DP of DP。我们在高位进行增加,那么我就不影响之前的位。我们记 表示当前让第 位增加 ,增加前 的值,第 位前面位的和的值,这一位增加 ,并记录增加之后 的值。
预处理之后,每次只要把询问的数在 进制下分解一下,求出最终 的值。
时间复杂度 。
CF1884E Hard Design#
我们先考虑如何对原序列计算答案的一种做法。
我们考虑按最大值建笛卡尔树。假设我们所在笛卡尔树节点为 ,在笛卡尔树上的父亲为 我们考虑在这个笛卡尔树区间操作 次。
考虑如何处理 。我们考虑组合意义,相当于是任意选两个位置的方案数。那么,我们现在考虑两个位置 能被同时选到的方案数如何计算。我们找到 的祖先 ,也就是说,在 即 的祖先之前, 都会被同时选到,贡献即为 。所以说,我只需要在 出计算两部分的贡献即可。
我们再考虑原问题。首先,最大值的左右两部分是独立的,因为最大值肯定不会被操作。那么,原序列就被划分成了两个部分,而这两个部分恰好对应了以最大值作为开头的一段前缀和一段后缀。
那我们就先可以出计算 表示 作为一对数的右端点的贡献, 表示 作为一对数的左端点的贡献。
计算时考虑建出笛卡尔树,然后计算左子树对右子树的贡献()以及右子树对左子树的贡献()。当然笛卡尔树并不需要显示地建出来,可以直接单调栈求出每个数作为最大值的区间即可。
然后再对 分别做前缀和、后缀和,即可得到前缀、后缀的贡献和。
时间复杂度 。
记录。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律