Day Inf【3、12~24】
Day3
列队:注意到学生的相对顺序不会变,然后你可以区间查询然后线段树二分加一点点简单的贡献计算解决。
可持久化串串:对 Trie 倍增,维护跳 nxt 的过程,如果 nxt 走的不超过一半,则这个串的后缀必然有循环节,跳过这些循环节找到最前面不规则那一段即可。
Day12
新知识:Dsu on tree。
在计算树上路径问题中,亦可使用点分治。
思想就是每次只保留重儿子的信息且回溯给父亲,其它点的信息暴力计算然后最后删除。如果是路径问题,记得加入一个子树过后要统一计算一次答案。
复杂度是线对,证明考虑一个点被暴力加的次数为对数次即可(假设加入删除复杂度均摊 \(O(1)\))
void Dfs(int x, int y, bool f) {
for(int to : G[x]) {
if(to == y or to == son[x]) continue ;
Dfs(to, x, 0);
}
if(son[x]) Dfs(son[x], x, 1);
for(int to : G[x]) {
if(to == y or to == son[x]) continue ;
for(int i = L[to];i <= R[to]; ++i) add(ifn[i]);
}
add(x);
ans[x] = get();
if(!f) {
for(int i = L[x];i <= R[x]; ++i) del(ifn[i]);
maxn = sum = 0;
}
}
至于习题,注意 >= k 的信息数组也是可以计算的。
Digit Tree:显然你考虑 LCA,然后路径分为上升段和下降段,我们在 dsu 的时候钦定了 LCA,枚举 x,那么用 map 记录之前加入的 y 的信息即可。
Day13
Deblo:拆位树上路径算贡献,简单题。
Ridiculous Netizens:树上依赖背包,考虑点分治计算所有点作为中心的答案,同时保证复杂度线对。至于背包部分,考虑根号分治,当 \(V\ge \sqrt m\) 的时候改成记录 \(m/V\) 即可,保证了状态数是 \(\sqrt m\) 级别。
感染:点分治优化前缀优化建图。容易发现一个点能连出去的点是树上是联通的,但是 dfn 不一定连续,但是如果点分治过后就是在一条路径上了。就是看新图中有多少点 in = 0。
考虑每个点拉出子树内所有点,按照 dis 排序然后连边,不用考虑同一条链上互相连边算重的情况,这并不影响。容易发现每个点练出去的都是一段前缀。直接前缀优化建图。
很好证最终边数在线对级别。
幻想乡战略游戏:点分树优化找重心的过程。选点分树根开始,向所有儿子走,判断移动是否优(唯一性)。这个判断就点分树上跳 fa,容斥掉 fa 在来源点的贡献。
Day14
Empty Rectangles:分治到中线 \(mid\)(行),枚举列 \(l,r\)。发现每个 \(k\) 都有一个行决策点。所以维护指针移动预处理,然后合并上下信息即可,复杂度 \(O(m^2k\log n)\)。
拦截导弹:三维偏序的 dp,用 cdq 套 bit 优化 dp。由于计算方案数,所以倒着再 dp 一次算出 i 作为起点的最大值方案数,和终点合并即可。
Day??? 初三杂题巩固
通配符匹配:显然分成多个分配符的段进行 dp,转移有 3 种,条件都是哈希判断,有一个 ? 的转移要前缀和优化。
稻草人:晚测,按照 y 的顺序加入点,就是线段树维护丹钓战的板子,虽然我不是很熟。。
赛道修建:显然一个子树只能上传 1 个有效路径,并且每次我们需要子树贪心地合并。贪心考虑从小的开始匹配。
Day17
矩阵乘法:整体二分,矩阵就是 01 的。
Sequence 数字序列:首先所有数减去 \(i\) 变成不严格旦增。二分的时候计算 2 个边界点的答案。
接水果:套了个二维偏序,注意第一维要强制小于第二维。对于时间轴我们要预先排序。
网络:判断一个点是否被完全覆盖。
Day18
炸弹:显然 ds 优化建图。缩点之后跑一个反向图的 dp,记录 L,R 即可。
PUS:一眼,限制只会划分成 \(O(k)\) 个段,考虑这 \(k\) 个点连向这些段,建一个虚点连向这些点,然后这个虚点用 ds 建图连向这些段即可,最后还是简单 dp 一下。
Tax:先考虑所有边都是出边,那么我们排序过后依次连边。又考虑入边,直接连向反边,边权为 0。想到这里自然地把边给变成点。建图很有网络流的味道。
Duff in Mafia:https://www.becoder.com.cn/article/15997
Day20
选举:显然所有 B 要先选,所以按照 b 排序,答案就是一段后缀全部选 a,前缀选一些 b,这玩意可以枚举选 b 的个数,然后 dp。
有趣的家庭菜园 2:前后互不影响,所以可以合并前后缀答案,线段树优化 dp。
有趣的家庭菜园 3:\(f(i,j,k,0/1/2)\) 表示前 \(i\) 个合法,当前是什么元素,我们考虑此时第 \(j\) 个 op 元素在当前状态下在什么位置,以及 \(j\) 这个地方考虑一下另外两个 op 的移位带来的影响。(显然相同元素相对顺序不会变)
配对游戏:对每一位算贡献,本质是长为 \(n-i\) 的随机 \(1/-1\) 序列前缀最小值不小于 0 的概率,或者可以直接按照题意 dp 转移。
Phoenix and Computers:1. 连续段 dp,很好写。
2.考虑在序列后面加入一段全部是手动开启的电脑段(一),然后中间间隔一个电脑来自动开启。转移系数就是相对顺序的交。然后还要算一下(一)的方案数。(枚举第一个操作位置,两边操作相对顺序固定,合并代价是组合数。这些组合数相加是一个 2 的幂)
Od deski do deski:\(dp(i, j, 0/1)\) 表示 \(len = i\),前面 \([1, x]\) 的合法位置有 \(j\) 个,当前是否是合法的,转移很简单。一般这种题都要升维。0/1 也是常规。
Day21
Tree:首先要选联通的。然后结论:边权和 - 直径。所以这个树背包算一下就可以了。
贪玩蓝月:删除操作很麻烦因为两端插入没办法维护前缀,考虑双栈维护前缀。现在考虑一个栈空了怎么办。一种方法是把另一个栈一半搬过来然后重新预处理。定义势能函数:\(F = |siz1 - siz2|\),一次插入/删除使势能变 \(1\),消耗 \(O(p)\)。一次重构消耗 \(O(Fp)\),让势能清 0,也就是变化 \(F\)。所以这样分析下来消耗 1 势能的代价是 \(O(p)\)。
合并的时候枚举一边 V,另一边用 st 表求区间 dp 最大值。
Polarization:最小值考虑每一层边方向一样,下一层方向取反。这样就是 \(n-1\)。考虑最大值,结论是选择重心,子树一些点全部向上,其余向下。(感性证明,如果你多个点这样的话贡献是不如一个点的)
那么现在就是背包合并所有子树的 siz。这是经典问题,用 bitset 优化可以 \(O(n^2/w)\)。但是这个题比较特殊,\(siz\) 和是 \(O(n)\) 级别,考虑根号分治。如果个数太多了,可以通过把一个 \(V\) 较小的物品的 \(cnt\) 二进制拆分给那些大的 \(2^kV\) 的数,复杂度 \(O(肯定能过)\)。
苹果树:明显选择一个叶子结点。然后做树上依赖背包。(可以先做一次 01 背包,再做多重背包,解决强制的问题)对一条链做前后缀的依赖,合并前后缀背包。(不妨后缀不选链,前缀选链)
弗雷兹的玩具商店 / Toyshop:\(m<60\) 就很奇怪啊。体积只有 60 种,明显只保留每个体积的 max 就行了。这个东西用线段树维护,每个节点存长度为 \(m\) 的数组。每个操作形如区间移动,区间加。询问就把 \(m\) 个物品取出来暴力 dp 即可。
Day22
字符串折叠:区间 dp,特殊处理一个区间全部循环节的贡献。
Jumping sequence:很明显还是要转坐标轴使得 \(x,y\) 独立吧。然后就是一些讨套路处理。
梦幻岛宝珠:\(b\le 10\),首先我们可以给每个 \(b\) 做背包,最后类似倍增并查集一样合并即可。如果记录剩下多少个那么上界就是 10n 级别。
波浪:连续段 dp,需要钦定左右是否碰到了边界,输出是勾石。
Elevators of Tamem:把 \(n\) 变成 \(q\),然后注意这一位一定有一维是 now,然后枚举哪一位是 lst 转移即可做到单次 \(O(q^2)\)。
New Year Shopping:线段树分治板题。删除操作就存背包数组即可。
Day23
括号序列:肯定要记录全是 * 的段,合法段,SA,AS 段,转移简单。但是合并会算重,所以强制合并合法串有一个是 (A) 类型的。
甲虫:发现可能走到后面露水负数了,所以我们还要钦定最终走到了 \(k\) 个露水,贡献就可以算了。
方块消除:显然要加维,表示后面加上和 \(col_r\) 颜色一样的数量。转移条件是 \(col_{mid}=col_r\)。
Coins Exhibition:可以容斥,但是我们可以对每段 dp,0/1/2 表示全 0/1,01 都有。转移 0/1 的时候就找到上一个 0/1 然后算一个后缀和即可。
Encoding Subsets:确定字符串 dp 很好做,3 次方即可,考虑子集。发现给循环节个字符串取交就是我们要求的东西(单个没有合并的),但是这玩意没法定义状态。不妨把字符串当做状态。然后简单。复杂度不是多项式刻画,能过。
Day24
Paint:显然可以合并成 \(r\) 的颜色,然后简单 dp。保证了 \(k\) 最多 20 个。
Candles:和昨天的题有所区别,可能中间是负数,那么我们状态加入【外面还剩多少个计算即可】。
字符合并:1:区间合并,按照不算重的套路,钦定后面只接入 0/1;2:整个区间操作,肯定最后只剩下一个 1,经典结论:\(n-1\equiv 0 \pmod {k-1}\),要加入辅助数组。整个串都合并成 0/1。1 的复杂度太高需要优化,发现后面能接入 0/1 的点都必须通过 2 合并,于是每次就移动 \(k-1\),能过。
Split and Insert:正难则反想到了,最终相当于要升序,操作变成将一段子序列移到后面去,这个东西刻画到值域上就好做了。显然我每次要把区间里面最大的数放到后面去,所以 \(dp_{t,l,r}=dp_{t+1,l,x}+dp_{t+1,x+1,r}+(r-x)\times c_t\),类似 01 背包,我们从大到小枚举 \(len\),做 \(k\) 次 dp 即可,这杨甚至可以省掉第一维。注意预处理最大值域上升段。
Chords:经典容斥。枚举断点,钦定前面一段合法/联通,后面全部内部连边。现在看起来确实显然 (9.17)。