Loading

近期总结11.14

看lby博客

CF623E Transforming Sequence

题意:求有多少个序列 \(a_{1...n}\)\(0\le a_i<2^k\),且令 \(b_i=a_1|a_2|...|a_i\),满足 \(\forall i,\space b_i>b_{i-1}\),答案模 \(10^9+7\)

\(1\le k\le 3\times 10^4,\space 1\le n\le 10^{18}\)


首先 \(n>k\) 答案为 \(0\)

每一位都一样,每个 \(a_i\) 至少有一位之前没有出现的 \(1\) 位。

\(f[i,j]\) 表示前 \(i\) 个数,\(b_i\)\(j\)\(1\) 的方案数。

\[\begin{aligned} f[i,j] &=\sum_{k=0}^{j-1} f[i-1,k]\times 2^k\times {j\choose k} \\ &= j! \sum_{k=0}^{j-1} f[i-1,k]\times 2^k\times \frac 1{k!} \times \frac 1{(j-k)!} \end{aligned} \]

后面是卷积的形式,但有个 \(j!\) 不好直接多项式快速幂。

考虑倍增,当 \(n\) 为偶数时递归处理 \(f[\frac i2 ,]\) 的值,然后就能直接做了。

需要写个 \(\text{MTT}\),比较麻烦。


CF710F String Set Queries

题意:一个字符串集合,每次操作有 \(3\) 种:

  • 插入一个字符串

  • 删除一个字符串

  • 给出一个文本串,求集合内字符串在文本串的出现次数之和。

强制在线。


一种新的数据结构——二进制分组

首先,有两种暴力思想:

  • 扫一遍集合内所有的字符串,计算答案。

  • 动态维护集合内字符串的 AC 自动机,让文本串在上面匹配,但每次修改需要重新建 AC 自动机。

前者修改快,后者查询快,考虑把两者结合起来。

先不考虑删除。

每次插入一个字符串,我们可以先给这个字符串单独建立一个 AC 自动机,称这个字符串处于单独的一组

当我们发现最靠后的两个组大小相同时,我们暴力合并两个组的 AC 自动机,这就很像 2048 消除。

时间复杂度证明考虑线段树。

然后删除操作开另一个二进制分组,插入和删除相减就是答案。


AGC035D Add and Remove

题意:给出 \(n,a_{1...n}\),这 \(n\) 个数排成一列。你每次删除其中一个下标 \(\in [2,n-1]\) 的数,然后他两边的数加上他原来的值。求最终 \(a_1+a_n\) 的最小值。

\(1\le n\le 18\)


不能状压啊

考虑区间 DP。

发现每次删一个数,会把他的贡献寄托给相邻两个数。

\(c(i)\) 表示 \(a_i\) 的贡献系数。

钦定删除 \(a_i\) 时其左边的数为 \(a_x\),右边的数为 \(a_y\),那么他的贡献系数为 \(c(i)=c(x)+c(y)\)

\(f[i,j,c_1,c_2]\) 表示消除 \(i+1...j-1\) 这一段,\(c(i)=c_1,c(j)=c_2\),最小的贡献和。

\[f[i,j,c_1,c_2]=\min_{i<k<j} \{f[i,k,c_1,c_1+c_2]+f[k,j,c_1+c_2,c_2]+(c_1+c_2)a_k\} \]

听说不用记忆化也能过,能证明出时间复杂度为 \(O(2^nn)\)

CF1887D Split

题意:一个排列 \(a_{1...n}\),每次询问 \([l,r](l<r)\),是否存在一个 \(p(l\le p<r)\),满足 \(\max_{l\le i\le p}\{a_i\}<\min_{p<i\le r}\{a_i\}\)

\(1\le n,q\le 3\times 10^5\)


这题的套路与之前一题一模一样。

以前我们都是枚举限制,然后维护条件

这里我们枚举条件,然后贡献限制

一个询问 \([l,r]\),可以考虑枚举 \(i(l\le i\le p)\),表示 \([l,p]\) 中最大值的位置。

那么 \([l,p]\) 中每个数都 \(\le a_i\)\([p+1,r]\) 中每个数都 \(>a_i\)

我们先不管所有询问,枚举这样的 \(i\),考虑他会对哪些询问区间做贡献。

\(L_i,R_i\) 表示左/右边第一个大于 \(a_i\) 的数的位置,可以发现,可以贡献的询问区间为:

  • \(l\in [L_i+1,i]\)

  • \(P_i\)\(R_i\) 右边第一个小于 \(a_i\) 的数的位置,\(r\in [R_i,P_i]\)

我们分别求出这些位置。

放到二维平面上,我们把每一个位置的贡献看做一个 \(x\in[L_i+1...i],y\in[R_i...P_i]\) 的矩阵,每次查询相当于查询 \((l,r)\) 这个点是否被至少一个矩阵覆盖。

扫描线即可,时间复杂度 \(O((n+q)\log n)\)

posted @ 2023-11-14 22:18  Lgx_Q  阅读(13)  评论(0编辑  收藏  举报