[CF-1148F] Foo Fighters
考虑将所有数按照 \(mark\) 在二进制下的位数进行分类,具体而言,设 \(p(x)\) 表示 \(mark_x\) 在二进制下最高的,为 \(0\) 的位置(可以认为 \(p(mark_x)=\lfloor\log_2 mark_x\rfloor\) ),将所有数按照 \(p(x)\) 分类。
接着按 \(p(x)\) 从小到大处理,假设当前枚举的数位为 \(P\) ,将当前 \(p(x)=P\) 的 \(val_x\) 都加起来,如果已经反过来了,\(s_P=0\) ;否则 \(s_P=1\) ,更新 \(val\) 。
[PKUSC2018] 最大前缀和
这里设定最大前缀和位为前缀和等于最大前缀和的最后一个位置。一个位置 \(p\) 是最大前缀和位当且仅当同时满足下列条件:
- \(\forall i\in[2,p]\cap \mathbb{Z}, \sum_{j=i}^p s_j\ge 0\) 。
- \(\forall i\in[p+1,n]\cap \mathbb{Z}, \sum_{j=p}^i s_j<0\) 。
稍微解释一下,因为这里最大前缀和位不能取到 \(0\) ,而最大前缀和位可能小于零,因此第一个条件的范围是 \([2,p]\) 而不是 \([1,p]\) 。
设 \(s(S)=\sum_{x \in S} a_x\) ,实际上我们可以求出每一个集合作为最大前缀对答案的贡献。接下来我们需要求出用 \(S\) 组合出的满足上述条件的序列个数。
设 \(g(S)\) 表示满足第二个条件的序列个数,可以得到:
设 \(f(S)\) 表示满足第一个条件的序列个数, \(f(S)\) 的转移和 \(g(S)\) 类似。
接下来组合答案:
[CF-526F] Pudding Monsters
一个区间 \([l,r]\) 满足条件,当且仅当 \(\max_{i=l}^r a_i-\min_{i=l}^r a_i=r-l+1\) ,当然,这里的等于号可以换成小于等于号。
考虑从左到右计算每一个 \(r\) 的贡献,显然可以用两个单调栈维护一下当且每一个 \(l\) 的 \(\max\) 和 \(\min\) 值,接下来将式子的右边移到左边,即变成:\(\max_{i=l}^r a_i-\min_{i=l}^r a_i-(r-l+1)\leq 0\) ,称左式为 \(l\) 的当前值,可以发现 \(0\) 是对于当前 \(r\) ,所有 \(l\) 的当前值的最大值。这时候可以用一颗线段树实现区间加,区间查询最大值和最大值个数。
[CF-963E] Circles of Waiting
Solution 1
容易得到转移方程:
将其移项,可以得到一个一个 \(5\) 元方程,尝试用高斯消元解决,但是状态数过大。但是可以发现消元的时候,对于每一个元 \(x_i\),其对其他方程的消元只会有 \(\sqrt{n}\) 次(这里的 \(n\) 是未知数个数),将未知数通过某种方式编号之后,可以使得这 \(\sqrt{n}\) 个方程在 \(x_i\) 的后面一段连续位置。因此总的时间复杂度为 \(O(R^4)\) 。
Solution 2
考虑取出某些状态,可以将剩余的状态看成这些状态的某条式子,这里可以取出原点和坐标轴上的点(其实可以随便取,怎么方便怎么来)。为了求出剩余点的式子,我们需要使用 \(\rm bfs\) (其实两个循环也可以)。计算的时候使用类似下列式子:
对于范围外的状态 \(f(i,j)=0 (i^2+j^2>R^2)\) ,可以认为有了多条方程,然后用高斯消元将原点和坐标轴上的点都解出来,然后算出剩余的状态(其实并不需要)。
[LUOGU-P4756] Added Sequence
有一个变形:
同时,因为只有整体加 \(x\) 一种操作,所以可以认为 \(s_i=S_i+ix\) ,这个形式可以认为是一条直线,将 \(x\) 看成斜率,\(i,s_i\) 分别看成横坐标和纵坐标,那么最大值和最小值只需要维护上凸壳和下凸壳即可。