24.11.21

A

怎么只有我一个写这种唐诗做法啊/kk

当括号匹配时会对若干区间造成贡献。
如果我们考虑每个右括号作为右端点统计贡献区间的话,左侧所有和它同一括号范围内(或最外层)的同层的左括号作为左端点和其构成一个贡献区间。
举例子来说
\(({\color{blue}(}))({\color{yellow}(}){\color{yellow}(}{\color{red})})\)
在上串中,在统计 \(\color{red})\) 作为右端点的区间时,那两个 \(\color{yellow}(\) 均与其构成贡献区间。
注意标蓝的左括号虽然与其层数相同,但是和它分别处于两个外层括号包裹下,已经隔了一层可悲的厚屏障了(雾不与其构成贡献区间。

对于左括号同理。

所以我们倒着扫一遍,对于每个左括号求出它右侧有多少右括号与其构成贡献区间,在差分数组上这一位就加上多少。
顺着扫一遍,对于每个右括号求出它左侧有多少左括号与其构成贡献区间,在差分数组上下一位减去多少。

如果我们记 (\(1\))\(-1\)
那么我们知道对于前缀和为 \(x\) 处的右括号与之匹配的左括号处的前缀和应为 \(x + 1\)
如果出现了右括号,其包裹的区间内的左括号不会再做贡献,所以将其包裹的区间里的左括号(前缀和为应为 \(x + 2\))的计数器清零。

对于左括号同理。与其匹配的右括号为 \(x - 1\),出现左括号时将 \(x\) 的计数器清零。


或者我们考虑另一种做法。
考虑每对匹配括号对其区间内的贡献

一对匹配的括号一定会对其区间内造成贡献。
此外如果左右有与其同层的配对括号那么与其拼接同样是合法的,
如果左侧的同层括号对数是 \(L\),右侧的是 \(R\),那么该括号对区间的贡献为 \((L + 1)\cdot(R + 1)\)


std 写的是第二种。
没有用差分区间加,子区间直接继承父区间的答案,再算自己新的贡献,这就是两侧匹配括号的答案,而再往里的子区间会继承它的答案计算答案。

麻了 A 这么唐一个题让我写题解怎么比 CD 题解加起来还长。写题唐写题解也唐是吧。

B

原到了 8.30 号。

何日重到苏澜桥-数论版。

理解一下 \(\gcd \neq 1\) 的情况,就是每乘一个 \(10\) 之后 \(D\) 就消去一个 \(2 > \times 5\)。然后 \(2^{20} > D\),就可以消去 \(2, 5\) 的影响。

PC 题解

\(h_i\) 表示 \(1\sim i\) 字符构成的十进制数字,即 \(h_i=\sum\limits_{j=1}^{i}s_i10^{i-j}\)

一个子串 \([l,r]\) 构成的十进制数字能整除 \(D\) 当且仅当 \(h_r-h_{l-1}\times10^{r-l+1}\equiv0\pmod D\) ,也就是说 \(h_r\equiv h_{l-1}\times10^{r-l+1}\pmod D\)

\(f_i\) 为以 \(i\) 为结尾子串不能被 \(D\) 整除的前 \(i\) 个字符的划分方案数,\(g_i\) 为以 \(i\) 为结尾子串能被 \(D\) 整除的前 \(i\) 个字符的划分方案数,

每次转移 \(f_i=\sum\limits_{h_i-h_{j-1}\times10^{i-j+1}\not\equiv0\pmod D}g_j\)\(g_i=\sum\limits_{h_r-h_{l-1}\times10^{r-l+1}\equiv0\pmod D}f_j+g_j\)

暴力向前扫是 \(O(n^2)\) 的,考虑优化。

\(\gcd(10,D)=1\),那么上述同余方程可以写成 \(h_r\times10^{-r}\equiv h_{l-1}\times10^{-(l-1)}\pmod D\),将 \(f_i,g_i\) 放进 \(h_i\times10^{-i}\) 对应桶里,每次查询桶里数的和即可。

\(\gcd(10,D)\neq1\),这时候 \(10\)\(\mod D\) 意义下没有逆元,不能用上述方法。

\(D\) 分解为 \(2^x5^yz\) 的形式。

那么同余方程可以分解为两个:

\(\begin{cases}h_r\equiv h_{l-1}\times10^{r-l+1}\pmod {2^x5^y}\\h_r\equiv h_{l-1}\times10^{r-l+1}\pmod {z}\end{cases}\)

如果要满足 \([l,r]\) 构成的十进制数字能整除 \(D\),必须同时满足上方两个式子。

由于 \(D\) 最大是 \(10^6\),也就是说 \(\max(x,y)\le20\),所以 \(r-l+1\ge20\) 的时候,\(h_{l-1}\times10^{r-l+1}\equiv0\pmod {2^x5^y}\)

此时需要判断的条件就变成了:

\(\begin{cases}h_r\equiv 0\pmod {2^x5^y}\\h_r\equiv h_{l-1}\times10^{r-l+1}\pmod {z}\end{cases}\)

\(\gcd(10,z)=1\) ,套用 \(\gcd(10,D)=1\) 的方法就行了。

而当 \(r-l+1 < 20\) 的时候不能这么做,这部分暴力向前扫 \(20\) 个就行了。

C

yyzz 题解

首先我们不考虑 “两个矩阵如果删除的元素位置不同,但最后得到的结果相同,我们认为是相同的” 这句话,可以得到一个朴素的 dp:\(f_{i,j}=\sum\limits_{j-k\leq l \leq j+k}f_{i-1,l}\),然后这个用前缀和优化转移即可做到 \(\mathcal O(nm)\)

回过头来观察这句话对结果的影响,同一行一段相等的元素,移除它们的结果是一样的,这意味着我们会计算许多重复状态,考虑去除重复贡献。

我们发现对于第 \(i\) 行相邻的两个相同元素 \(j-1,j\),它们对应上一层的范围是这样的:

(红线为 \(j-1\),蓝线为 \(j\)

显然,上图中被白线框出来的线段被重复覆盖了,这一段为 \([j-k,j+k-1]\)

我们新增一个数组 \(g\) 来记录每个元素可能会重复计算的贡献,那么 \(f\) 的转移方程就不难推出:

\[f_{i,j}=\sum\limits_{j-k\leq l \leq j+k}f_{i-1,l}-\sum\limits_{j-k+1\leq l \leq j+k}g_{i-1,l} \]

注意 \(g\) 的起始位置为 \(j-k+1\),因为左端点不会产生重复贡献。

根据 \(g\) 数组的定义和我们上面推出的式子,可以得到转移:

\[g_{i,j}=[a_{i,j}=a_{i,j-1}]\times (\sum\limits_{j-k\leq l\leq j+k-1}f_{i-1,l}-\sum\limits_{j-k+1\leq l\leq j+k-1}g_{i-1,l}) \]

答案即为 \(\sum\limits_{1\leq i\leq m} f_{n,i}-\sum\limits_{2\leq i\leq m} g_{n,i}\)

然后这个也是从一段区间转移,前缀和优化即可,时间复杂度 \(\mathcal O(nm)\)

D

NT 题解

首先对于询问我们可以发现最后的答案一定是形如下图:

并且最大的边一定在左右两侧中的一侧。

那我们考虑 kruskal 从小到大加边,每次去合并连通块,因为我们是从小到大加的,所以最后答案一定会变成下图:

那么我们考虑合并的时候将出边和询问都合并到一个点上,使用启发式合并可以做到 \(O(n\log^2 n)\)

不是您搁这打 CodeGolf 呐?

把询问存到点上(存对应另一个点和编号)。

思路是这么个思路,里面计算答案和合并的过程感觉不如换张图理解:

启发式合并中,不妨使 \(x\) 为边数和询问数较少的集合。

如果我们现在最小边是蓝边,我们要计算以其作为答案即次大边的询问。
它已经是当前最小边了,要计算以其为次大边作为答案我们就要走且仅走一条其他边,由于 \(x\) 边数和询问数更少,所以

  • \(x\)\(y\) 的出点,查 \(y\) 中是否有询问这个出点的,回答那些询问;
  • \(x\) 的询问,查 \(y\) 是否有这个询问的出点,回答那些询问。

合并就是合并。把边和未回答的询问放到一个点上,由于 \(x\) 较少,所以把 \(x\) 的边和询问插到 \(y\) 里。

注意也要更改别的集合的出边和询问,让原来指向 \(x\) 的边和询问指向 \(y\)

posted @ 2024-11-21 17:30  KinNa_Sky  阅读(6)  评论(5编辑  收藏  举报