NOI 前杂题乱写

口胡标*

LOJ 3320

每个点开始搜。找到两个颜色的分界点,延长路径时根据新加入的点和分界点的连边颜色可以将它安排到分界点以左/右。

时间复杂度 \(\Theta(n^2)\)

CF1427F

由于有解,那么做一次三个栈顶元素相同就弹出的单调栈是在最后一定可以将所有元素弹空的。同时弹栈的元素分为一组,同组元素将会在一次操作中被拿出来。单调栈的过程也可以求出来两个组之间弹出时间的大小关系。它们形成了一棵森林,两个人轮流操作本质上是在剥叶子。

这时候只要保留一个后手操作的树的根,剩下的叶子随便剥。直接通过 \(01\) 数量和父子关系对数量的以来可以反证得到。

UOJ386

将所有物品按照 \(s\) 排序。在选择物品数量 \(<m\) 时选择的一定是一段连续区间。否则可以添加上下界里面的空位置来做到只让被减数增加。

不连续的部分将 \(m\) 从小到大从序列中删除,统计被删除元素作为 \(m\) 个选出来的数字中 \(v\) 最小值的方案。这个直接找在序列上没被删除的元素中前面 \(m-1\) 个和后面 \(m-1\) 个,并枚举长度为 \(m\) 的区间计算答案。

插入删除找前驱后继,使用双端链表来实现即可。

时间复杂度 \(\Theta(nm)\)

UOJ388

我的想法需要二维平面单调栈,在搞笑。

直接让 dfs 序排序之后两两配对的另外一种表述就是子树里面剩下奇数个就要让子树根的返祖边被覆盖一次。那么在每个点的父子边处统计答案即可。

于是直接统计有几种选择左右端点的方案使得 dfs 序区间里面有奇数个数字,写成模 2 同余的形式即可。使用线段树合并维护 id 存在的点,线段树上维护前缀和奇偶性的端点数量。

CF809D

\(f_i\) 表示结尾权值为 \(i\) 的最大长度,不难发现只有前缀单调栈里面的元素对于转移有用。

再看两眼,归纳一下发现单调栈中相邻元素权值之差为 \(1\) 。转移就变成了下加一,权值加一,两个端点新增加 \(\rm DP\) 值。

一个 fhq Treap 实现

UOJ351

圆心确定后答案只和每个连通块的半径距离叶子数量有关,枚举没删完的连通块和剩下的数量。预处理染黑 \(i\) 个点的期望步数 \(\displaystyle\sum_{j=1}^i\frac{n}j\)

设剩下的连通块中叶子数量为 \(k\) 个,将所有点任意排列作为总方案数,被染黑的点要排列,没有被染黑的点也要排列。

这里会出现的一个问题就是要差分剩余数量,即任意排列时有比当前枚举数量更长的一段后缀都是这个连通块中的点,此时出现了不合法方案。

二项式反演不知道行不行,但是钦定最后一个染色的不属于这个连通块是容易的。

UOJ193

直接数了半小时放弃了。

根据实际含义,每棵基环树的权值就是给节点黑白染色,强制叶子染白色,其他任选。容斥黑色叶子集合,剩下是一棵基环树,节点颜色任选,容斥系数是黑色叶子数量。那么计算黑色和任选之间的连边方案数和某个集合形成基环树的方案数即可

前者就是单点出边终点落到某集合数量的乘积。后者可以 \(\rm DP\):初始化每个集合为成环的方案数(钦定某个点为环上标号极值一步一步走),接下来逐层添加节点。但是要容斥,因为层上的节点可能没产生连边而导致算重。这和 DAG 计数完全一样:考察一个合法方案的统计次数,它的每个叶子集合都被计算了一次,根据二项式定理得到系数 \((-1)^{|T|+1}\)

LOJ2788

你真的需要这么多边吗?

建出来生成森林,于是剩下的边不可能是割边。于是只考虑一棵树的非树边。

比较基础的想法就是每条非树边覆盖的树边都不会是割边。但是还是需要存下来所有非树边打标记。

你真的需要这么多边吗?

非树边成环了则打标记的效果也就没了,于是找到非树边的生成树打标记即可。

HAOI2018 反色游戏

如果一个联通块里面黑色点的数量是奇数那么一定无解。对于一棵树就可以通过剥叶子得到解。存在非树边时,非树边任选的情况下树上的黑色点数量的奇偶性是不变的。

某个点删除之后带来的最直接影响就是非树边数量。其次就是连通性:联通块数量会变化。

如果它在某个点双里面肯定不会带来影响,否则需要处理 dfs 树子树中黑点数量,是否存在子树的黑点数量为奇数。对于父亲所在联通块的信息可以通过处理每个联通块的总信息来得到。

ARC136E

在下述讨论中对 \(1\) 号节点的处理都比较简单,先略去不写。

\(f(i)\) 表示 \(i\) 的最小质因子。那么 \([i-f(i)+1,i-1]\) 中的点和 \(i\) 没有边相连,\(i\)\([i+1,\min(n,i+f(i)-1)]\) 中的点没有边相连。

那么尝试考察两个点 \((x,y)[x<y]\) 不满足 \(x\) 可以走到 \(y\) 的条件:

  • \(x\) 是偶数,\(y\) 是奇数。此时 \(y-f(y)\)\(x\) 可以直达的,约束就是 \(x>y-f(y)\)

    类似地,\(y\) 是偶数而 \(x\) 是奇数的情况需要满足 \(y< x+f(x)\)

  • \(x,y\) 均为奇数时 \(x+f(x),y-f(y)\) 都是偶数,于是需要满足 \(x-f(x)>y-f(y)\)

尝试在交集处统计答案,也就是说将奇数点点权通过差分下放到 \([x-f(x)+1,y-f(y)-1]\) 而偶数点点权只下放到自己处。于是选择一个下放后最大的权值和即可。\(1\) 的权值直接加进答案

CF1616G

建立一些虚边:\(0\)\(1\dots n\) , \(1\dots n\)\(n+1\) 连。那么此时路径一定形如 \(0\to x\to y\to n+1\)\(x>y\)

\(0\to x\) 的路径上的点上标 \(0\) ,在 \(y\to n+1\) 的路径经过的点上标 \(s_i=1\),于是 \([0,y)\) 上都标注了 \(s_{i}=0\)\((x,n+1]\) 上的点都标了 \(0\)。只在 \(s_{i}\neq s_{i+1}\) 处进行处理,此时只用考虑起点终点差 \(\ge 2\) 的边

尝试计算每个 \(y\) 的答案。设 \(f_{i,0/1}\) 表示只考虑长度为 \(i\) 的前缀 \(s_i=0/1\)\(s_{i+1}\neq s_i\) 的方案数,枚举每条边找到上一个节点即可,限制就是这段区间中的点需要可以通过 \((i,i+1)\) 边可达

找到最小的不存在 \((i,i+1)\) 边的 \(L\)\(f_{i+1,* }\) 是枚举每个 \(y\) 时都需要的。那么可以让 \(i+1\) 的两种选法分别具有两种状态 \(1,2\)\(f\) 值变成可以实现两种状态的哪种,分别对 \([L+1,n+1]\)\([1,L+1]\)\(\rm DP\) ,如果值代表的状态有重叠那么就可以连边,对 \(\rm DP\) 值开桶记录即可

注意减掉只有一个 \(i\) \((i,i+1)\) 没有连边的情况。这时候有一种直接连的不合法方案被统计了

AGC024F

\(f_{S,T}\) 表示 \(S\) 串还没有匹配,在之前匹配过程中得到的串是 \(T\) 的方案数,初始化为给定的字符串中为 \(1\)\(S\)\(f_{S,\empty}=1\)

转移的过程中可以选择 \(T\) 中下一个元素选 \(0\) 还是 \(1\) 可以得到新的 \(S\),新的 \(S'\) 可以先一开始的递推得到

最终从满足 \(f_{\empty,T}\ge K\) 的那些中找字典序极值。

其实问题都是实现上的,首先发现 \(|S|+|T|\le 20\) ,于是可以通过枚举 \(|S|\) 来分成转移的阶段。最终 \(T\) 的长度可以在最后放一个 \(1\) 来标识

Luogu8125

\(\displaystyle L_i=\max_{1\le j\le i,t_j+(i-j)\ge i} j\) ,那么要在 \([L_i,i)\) 之间的空隙中放一个垫子才可能不让 \(i\) 逃脱

不难发现 \(L_j< L_i< j< i\) 的情况不会出现,否则 \(j\) 应当受到 \(L_i\) 影响。于是这样子的区间只有包含和相离的关系。

覆盖一个较短区间可以让一个较长区间也被覆盖,如果将上述关系建成树则覆盖叶子有覆盖祖先的效果,找前 \(k\) 长链即可

AGC020D

最小的连续段长度是将较少者将较多者均分,也就是 \(\frac{A+B}{\min(A,B)+1}\)

字典序最小一定形如 \(AA\dots ABAA\dots AB\dots AABBBA\dots BB\dots BA\dots\) ,于是可以二分\(B\) 为主的连续段从哪里开始,判据就是 \(A\) 的数量是不是够给后面的 \(B\) 插空

注意 \(A\) 主导的连续段结束之后 \(B\) 的第一个主导段放的是最后结尾的剩余

AGC015E

这题不能尝试将 copies 按照速度从大到小加入了。

先考察只染色一个 copy \(i\) 能带来的连锁反应,坐标小于 \(x_i\) 且速度大于 \(v_i\) 的 copy 可以被染色;坐标大于 \(x_i\) 而速度小于 \(v_i\) 的 copy 也可以被染色。

此时坐标大于 \(x_i\) 的 copies 中速度小于 \(i\) 处速度前缀 \(\max\) 的也会被染色,同理,坐标小于 \(x_i\) 且速度大于后缀 \(\max\) 的 copies 会被染色

\(f_i\) 表示坐标前 \(i\) 小的 copy 都被染色的方案数,转移尝试枚举上一个被染色的 copy \(j\) 。限制为中间不能有速度空隙,可以双指针扫出来合法的转移点区间,配合前缀和做到 \(\Theta(n)\) 转移。

AGC027F

子树没到位之前祖先是不能动的,而 \(B\) 中祖先没处理完之前子树不能连过去,于是构成了拓扑关系

如果存在一个点没有被操作过,将其提根得到有根树,可以据上判断是不是存在操作序列,其长度就是需要修改父亲的点数

如果都操作过就枚举第一步操作 \(u\to v\) 并将 \(u\) 提根再执行上面的步骤,注意 \(u\) 要满足是叶子。

由于第一步操作有 \(\Theta(n^2)\) 种于是复杂度是 \(\Theta(Tn^3)\) 。有不枚举 \(v\) 的做法没看懂

AGC010F

从一对点中非较大者(\(\le\))挪到另一个后对手可以再挪回来,必然是这个点本身先被耗尽。

所以如果某个点周围的石子数量小于之的点是必败的那么它就是必胜的,按照石子数量从小到大遍历即可

AGC026E

\(pa_i\) 表示第 \(i\)\(a\) 出现的位置,同理 \(pb_i\),另有 \(id_i\) 表示第 \(i\) 个字符是第几个 \(s_i\)

\(f_i\) 表示只考虑后 \(i\)ab 时得到的字典序最大的字符串,转移有保留和删去两种策略,删去则直接继承 \(f_{i+1}\)

那么下面强制保留第 \(i\)ab

如果 \(pa_i<pb_i\) 那么在 \(pa_i\) 之后 \(pb_i\) 之前的所有 \(a\) 应删去,又由于只考虑第 \(i\) 对和以后的元素 \((pa_i,pb_i)\) 中的 \(b\) 也不会被保留,那么找到 \(pb_i\) 之后所有的 \(\min(pa_j,pb_j)>pb_i\) 最大的 \(j\) 转移即可

对于 \(pa_i>pb_i\) 的情况则 \((pb_i,pa_i)\) 中的 \(b\) 都应被保留,\(a\) 都不属于第 \(i\sim n\) 对字符,所以直到 \(pa_i\) 会出现第一个 \(a\)

此时由于钦定保留了一些 \(b\)\(pa_i\) 和它们对应的 \(a\) 的位置中间仍然有 \(b\),这些仍需要保留,所以暴力找到第一个满足不需要额外钦定的位置继承 \(f\) 即可

CF1408I *

先计算出来全部 \(a_i\) 的异或和 \(X\),减小若干 \(a_i\) 后再求异或和本质上是让 \(\rm X\) 异或上 \(a_i\oplus (a_i-d)\)

本题中的概率本质上是算序列数,所以设每个元素的 \(\rm EGF\)

\[F(n)=\sum_{i=0}^{K}\cfrac{x^{a_n\oplus (a_n-i)}y^i}{i!} \]

其中 \(x\) 一维的指数运算是异或而 \(y\) 这维是加法,表示被操作的次数

如果可以求出来 \(\rm EGF\) 的乘积本题便迎刃而解了

考察本质不同 \(\rm K\) 元组 \(\{x\oplus (x-1),\dots x\oplus(x-K)\}\) 的数量级,取出后 \(\lceil\log_2K\rceil\) 位记作 \(t\)

如果 \(t>=K\) 这样的元素只会有 \(\Theta(K)\) 个,否则退位会影响到 \(c\) 个中的每一个,而每个退到的位都有 \(K\) 种可能,那么总数量级为 \(\Theta(cK)\)

此时得到的一种做法就是直接跑 \(\ln,\exp\) 来计算每种 \(\rm EGF\) 的快速幂,但是复杂度很高

尝试对于 \(\Theta(cK)\)\(\rm EGF\) 固定 \(K+1\) 个中的一个 \(y^t\),此时做 \(\rm FWT\) 前的序列只有一个位置有值,那么 \(\rm FWT\) 后每个 \(x\) 上的元素均为 \(\pm \cfrac{y^t}{t!}\) 中的一个

那么将 \(K+1\)\(\pm 1\) 压下来做 \(\rm \ln,\exp\) 再快速幂即可通过

这种通过 转变考察维度 来减少运算量的技巧非常厉害!

CF1396E *

拨开迷雾见月明

这个完美匹配是在诈骗,本质上是给树上的点两两配对,每对点的贡献是两者在树上的距离

既然是距离所以可以通过 \(d_x+d_y-2d_{\rm LCA(x,y)}\) 来统计,取出树的重心作为根,每次选择当前剩余点最多的两个子树中选出来一个点配对并删去

此时得到最大的距离和 \(\sum d_i\) ,同时不难找到最小的距离和:让每个点的儿子互相配对,如果有剩余则自己和其儿子配对,这时距离和为 \(\sum siz_i\bmod\ 2\)

后面构造的部分是平凡的

先判定 \(\rm K\) 不在值域内和 \(\rm K\)与最大值的差为奇数 的两个不合法情况,每次取出根的剩余点最多的一棵子树进行调整:

找到剩余点最多的子树并找到其最深的非叶子让它作为 \(\rm LCA\) 进行配对,如果其深度已经超过当前 \(\rm K\) 那么找到该点根链上深度为 \(K\) 的点让它和它儿子配对;没有超过就让该非叶子子树内配对并改变 \(\rm K\) 的数值

使用 std::set 维护重心所有儿子子树里面的点来实现上面的配对步骤,找剩余点最多的子树用优先队列,复杂度 \(\Theta(n\log n)\)

UOJ667

将括号序列转成树

\(\rm DP\) 的状态中记录 \(\rm B,R\) 选了几个会吃大亏,所以使用 “是否选择过” 的套路来做,根据本题的限制需要选择 \(1\) 个白球和两个黑球

\(f_{i,j,0/1,0/1,0/1}\) 表示在 \(i\) 的根链上有 \(j\) 个选择白色的点,是否选择过白球、第一个黑球、第二个黑球

转移枚举当前点的颜色以及是否当做被选中的元素即可

为了方便处理,可以通过深度得到每个点根链上选择白球数量的上下界,那么每个点的状态可以变成 “不包含当前点的根链上有几个白点”,枚举到这个点是白点的时候让第二维减一即可

CF1158F*

只能说题蠢我更蠢

判定一个序列的密度有非常简单的方法:找到 \(1\sim c\) 每个元素的第一次出现并把出现位置下标最大值作为结尾的前缀删掉,能删多少次密度就是几

据此可以得到一个针对元素是否出现的 \(\Theta(\frac{n^2}c2^c)\) 的状压 \(\rm DP\) ,添加到全集就让密度加一,全集变空集

\(c\) 较大时需要另编一种做法,设 \(f_{i,j}\) 表示从 \(i\) 开始的后缀密度是 \(j\) 的方案数,转移直接添加全出现过的一段

为了防止重复还需要钦定最后一个元素是这段里面唯一一次出现(长度非 \(1\) 时左右端点值不同),系数自然是选择子序列里面是不是包含某个元素,设 \(c_i\) 表示 \(i\) 的出现次数,合法区间的转移系数是
\(\displaystyle 2^{c_{a_l}-1}\prod_{i\neq a_l\& i\neq a_r}2^{c_i}-1\)

当然需要前缀和优化,同时需要对密度这一维度上界精细化实现做法复杂度 \(\Theta\left(\dfrac {n^3}c\right)\)

CF1375H*

将序列分成 \(B\) 个值域连续段,每段 \(\dfrac nB\) 个元素

对每个段里面的所有下标连续段维护一个集合,那么查询在每个段里面二分左右端点即可得到 \(\Theta(q\frac{n}B)\) 的操作次数的做法

对于段里面的元素按照权值分治,分治结构的叶子直接返回自身,否则枚举左右子区间的每个下标作为左右端点,找到子区间在该区间中的元素形成的集合的标号,合并成一个新集合

合并操作次数可以通过 \(T(B)=\frac{B^2}2+2T(\frac B2)\Rightarrow T(B)=B^2\) 得到结果为 \(\Theta(nB^2)\)

平衡一下即可得到总操作次数约为 \(2n\sqrt Q\) 的做法!

CF1103D*

求出 \(\rm GCD\) 之后将 \(a_i\)\(\rm GCD\) 部分消去,据说剩下不同的数字最多就 \(12000\) 种了,显然每种数字只需要最小的质因子种数个,互异因子显然也只有 \(m=11\)

\(f_{k,S}\) 表示使用的 \(k\) 个数字后仍然保留了 \(S\) 中的因子的最小 \(\sum e_i\) ,用 \(12000\times m\) 个数字更新这些状态也不赚,所以可以先预处理转移集合

注意这里 \(k\le m\)

考虑每种数字对于哪些因子的消去是可行的,那么对于质因子的一个子集 \(S\),没有必要使用所有的 \(12000m\) 个数字都转移一遍,如果能预处理出来能消去 \(S\)\(e_i\) 最小的 \(m\) 个数字

转移复杂度此时降到了 \(\Theta(m^23^m)\) ,可以接受;但是繁琐之处在于预处理时 \(12000\times 2^m\) 次更新最优转移集合,需要使用归并排序等来精细实现

CF1097E*

构造半天想不到段数大于 \(\min\{B,\dfrac nB\}\) 的序列,那就猜根号!

严谨思考一下好像是有 \(\max \{\frac{(L+1)(L+2)}2\}\) 的界,尝试来构造性证明一下

先找一个 \(\rm LIS\) 出来,根据 \(\rm Dilworth\) 定理不难发现此时必然存在一种将所有下降序列分成其长度组的方法

如果这个 \(\rm LIS\) 够长直接删掉,可以规约到子问题,否则直接贪心取出来所有下降序列即可(此时的链划分就是能分就分,不行就新开一组)

所谓 “够长” 的临界值可以通过上面的界来判定

CF1608F*

\(f_{i,j,mex}\) 表示前 \(i\) 个数字中有 \(j\) 数字 \(>mex\) 的方案数

\(f_{i,j,mex}\) 转移到 \(f_{i+1,j,mex}\) 的系数显然是填无关紧要的数字种数,也就是 \(j+mex\) ;新增 \(j\) 的方案延后计算,即转移给 \(dp_{i+1,j+1,mex}\) 的系数是 \(1\)

最后一个 \(\rm case\) 就是令 \(a_{i}=mex\) 来进行增加,设新的 \(mex=t\),注意到这 \(j\) 个大于 \(mex\) 的数字出现哪些都是等方案数的,系数就是排列数 \(\binom{j}{t-mex-1}(t-mex-1)!\)

显然 \(mex\) 这一维度只有 \(\Theta(K)\) 个位置有值,直接对位进行系数附加复杂度是 \(\Theta(n^2K^2)\)

那么可以前缀和优化,把阶乘放到一侧处理,此时要简化前缀和的细节可以把状态定义成 \(dp_{i,j+mexf,mex}\),那么阶乘的内容就变成后两维度的差了

CF1438F

不是很 OI 的题目

经验之谈显然有随机找三个点问 \(420\) 次,然后根据得到的回答根据某种策略问所有点

(当然可能是先问所有点,再根号找根,但是出题人没开到 \(520\) 次说明不是这个做法!)

平凡观察得到每次询问可以找到一个三叉结构,但是根据随机化思想现行目标是找到一些出现概率比较大信息再进行 \(n\) 次询问

注意到这个三叉结构如果有两个是根的某一侧那么得到的回答就是根的一个儿子,这种情况显然出现概率比三个点都撞到根的同侧子树要大

那么问 \(420\) 次得到的出现次数最多的两个点可以被认为是根的左右儿子,那么询问 \((ls,rs,i)=i\) 的就是根

CF1558F

将加入过程转变成 \(01\) 序列翻转一个位置。或者理解为对于 \(1\sim n\) 的每个 \(i\) 求出将 \(\le i\) 的元素(0)都排到 \(> i\) 的元素(1)左边的最小值。

\(f_{i,j}\) 表示有 \(i\)\(1\)\(j\)\(0\) 左边,将所有 \(0\) 交换到所有 \(1\) 左边的最小步数,转移为是 \(f_{i,j}=\max\{f_{i+1,j},f_{i,j-1}\}+1\) 归纳两下可以发现交换次数就是每个位置前 \(1\) 的数量加每个位置后 \(0\) 的数量。在 不合法状态下(前面有 \(1\)/后面有 \(0\)) 还需要考虑这个位置的奇偶性

那么可以使用线段树来维护 \(01\) 序列的变化,翻转位置对答案饿影响是区间加,而要求该位置不合法可以用激活 \(-\infty\) 来实现。答案就是对每个 \(01\) 序列的每个位置的最大值求最大值。

CF908D

Luogu 翻译错了错了错了!原文中就是问 ab 作为 subsequence 的期望次数!

钦定 \(a\) 作为序列首,设 \(f_{x,y}\) 表示有 \(x\)\(a\)\(y\) 个子序列的概率,填 \(b\) 得到 \(f_{x+1,x+y}\) 否则得到 \(f_{x+1,y}\)

根据 真实的题目描述,当 \(x+y\ge K\) 的时候将 \((x+y)f_{x,y}P_B\) 附给答案,而对于 \(f_{K,i}\)\(i<K\) 的情况,后面可以继续缀上一段连续的 \(a\) 然后填一个 \(b\) 来满足条件,此时的贡献形式时等差乘等比,列出计算式子得到答案即可

CF1179E

原来不敢看,现在看看确实有绝妙一步非常神仙!

直接的思路时找到所有 \(f_i(x_i)=\frac L2\) 并取出 \(\{x_i\}\) 的中位数,对于 \(x_j>x_i\)\(j\) 说明其在 \([0,\frac L2]\) 的值域段对应的定义域大,否则说明 \((\frac L2,L]\) 对应的定义域大

那么将所有函数分成两部分向自区间分治就可以得到询问次数为 \(\Theta(n\log V\log n)\) 的做法

注意到此时我们只关注中位数的 \(x_i\) 的具体值,得到中位数之后判定 \(x_j>x_i\) 的部分也可以用每个函数在 \(x_i\) 的点值和 \(\frac L2\) 的大小关系来得到,不二分复杂度将降到 \(\Theta(n\log n)\)

此时问题转化成了快速找到中位数,那么可以在备选集合中随机一个函数出来判定 \(x_i\) 小于/大于之的数量,此时期望随 \(\Theta(\log)\) 轮可以找到

这样子我们就得到了一个总操作次数为 \(\Theta(n(\log V+\log n))\) 的做法

CF768G

最大的联通块大小有三种来源:次大值,最大值减去对应点其某棵子树大小,最小值加最大值补过来的联通块大小

如果可以维护最大联通块的所有子树大小以及其余联通块中最小以及最大的两个可以通过二分得到某个点答案

后两者可以通过求子树大小得到,那么尝试对所有点维护 “最大联通块的所有子树大小”

最大联通块的来源有 以儿子为根的子树 和 除了这个子树之外的联通块 两个,前者可以通过启发式合并得到对应集合,为了配合上面的二分,需要写个 std::set

后者分为非根链上点的子树大小以及根链上点的子树大小减去当前点子树大小,后者可以通过 \(dfs\) 以及撤销来得到,做减法在二分时并不碍事

观察在朴素 \(\rm DFS\) 的时候前者的增量启发出 \(\text {dsu\ on\ tree}\) :先递归轻儿子再将轻儿子都加入 set 去递归重儿子,完成后二分当前点答案,每次返回时保证以子树中点为根的子树大小在 set 中删去

时间复杂度 \(\Theta(n\log^2n)\)

CF908H

每个 \(\rm SCC\) 中不能有 X 的关系,可以先将 A 用并查集缩起来后据此判定无解

如果得到了所有 \(\rm SCC\) 的构成,那么答案就是 \(siz>1\)\(\rm SCC\) 数量 \(+n-1\),也就是将所有 \(\rm SCC\) 连成一条链

忽略掉孤立点,现在需要求出最少需要几个 \(\rm SCC\) 可以将所有点覆盖,注意到此时每个 \(\rm SCC\) 大小 \(\ge 2\) ,所以只有 \(\frac n2\) 个,可以状压 \(\rm DP\)

注意到这个状压 \(\rm DP\) 本质上是对所有合法子集进行或卷积(不要求子集无交),所以可以直接对着点值操作,每乘一次点值根据预处理的 \(\rm IFMT\) 系数判定是否能凑出来 \(U\) 即可

说了这么多,问题来了:为啥我代码写的是 \(\rm IFWT\) 的系数也通过了呢?

CF1267G

存在最优策略使得先随机,再逐个购买;策略随机的时候随机得到每个子集的概率都相同

那么开始逐个买后,每个元素的购买顺序是无所谓的,所以也可以将逐个购买转化成花费总代价的 \(\frac{k}{m}\) 得到 \(m\) 个剩下元素中的任意一个

那么设 \(f_{i,S}\) 表示选择 \(i\) 个元素总和为 \(S\) 的概率,可以根据继续随机得到元素的花费 \((\frac mk+1)\frac x2\) 以及直接购买的花费 \(\frac{S}m\) 的大小比较得到下一步的最优策略

\(f\) 可以根据定义配合吸收恒等式进行转移

将每步每种情况执行最优策略的代价求和可以得到最终答案

LOJ2391

如果两个区间 \([a,b],[c,d]\) 满足 \(a<c<b<d\) 那么在这两个点之间连一条边,那么原问题就是求解图中联通块个数 \(c\),答案是 \(2^{c}\);当然如果连完边的图不能黑白染色结果就是 \(0\)

根据区间得到 \(1\sim 2n\) 中对应的区间的左端点还是右端点

从左往右扫描,维护一个集合 \(S\),如果该元素是作为左端点出现那么将其放到集合中,如果是作为右端点就从集合中删去,同时将当前点和这个集合中加入时间晚于之的点连边

注意到这些仍然在集合中的元素在经过这个点之后将被钦定成同色点,那么可以动态维护 \(nxt_i\) 表示和 \(i\) 同色的点最远延伸到了哪里

在集合中删除元素也用并查集维护,即删去一个就将它和右侧点,每次 “找 \(nxt_i\)后面的一个” 直接在并查集上跳即可

由于同色而缩到一起的元素都和当前点连边了,所以在后续的黑白染色中可以达到同色的效果;而 \(nxt\) 指针和并查集路径压缩是完全一样的,那么总时间复杂度 \(\Theta(n\log n)\)

LOJ3077*

首先建立生成树,那么每条非树边都带来一个环,那么最多 \(3\sim n\) 的环各一个,所以实际上 \(m>2n\) 答案一定是 Yes

随机删掉 \(\sqrt n\) 条边期望剩余环的数量是根号 \(n\)(考察每个环全部不被删除的概率即可) ,注意到这时随机情况下,那么 \(m>n+2\sqrt n\) 的时候 Yes 就一定被输出了

将剩下的非树边短点拉出来建立虚树,在上面跑爆搜(搜索回溯,每到一个点用 \(\Theta(m)\) 判断如果当前点不再能到达起始点就返回),搜到起始点就给对应带权环数量加 \(1\) 并统计经过虚树上点的个数

不难发现如果两个等长带权环如果经过点数不同就出现等长环,而每个带权环会被统计二倍经过点数次(每个点作为起始点和双向),这也可以作为判定等长环出现的标准

这种爆搜复杂度是 \(m\sum_{i=3}^n (len=i)\times (tim=i)=n^3m\) ,也就是遍历次数乘每次遍历代价,代价就是长度,每个点还得检查能不能到起点,所以额外乘 \(m\)

总复杂度 \(\Theta(n^4)\)

CCPC广州2021 J

先将 \(\rm DP\) 转移写成矩阵乘法,然后发现区间查询本质上是求出来前缀积和其逆元的乘积的某个位置

由于初始列向量只有一个位置有值,而且最终只关注一个位置,所以只存下来逆元的 \(0\) 行和前缀积 \(m\) 列就行了,询问复杂度 \(\Theta(Tm)\)

注意这里应当是按照 \(iM_{l-1}\dots iM_{1}M_1\dots M_r\) 的顺序来进行矩阵乘法,也就是添加逆元的时候要左乘,而前缀积时右乘

不难发现转移矩阵只有对角线和匹配位置有 \(1\),直接对有值的地方做列变换复杂度就是 \(\Theta(n^2)\),而逆矩阵也是类似的,在非对角线上的位置做行变换的减法形式即可

CCPC广州2021 K

容斥,计算 \((\sum_{i=1}^m i)^n\) 减去 \(\gcd >q\)\(\gcd \le q,{\rm lcm}<p\) 的部分即可

\(\gcd>q\) 这部分可以倒序计算每个数作为 \(\gcd\) 的总和,直接用总方案数减去是当前元素非本身倍数的结果即可

对每个 \(k\) 预处理 \(gcd=1,lcm=k\) 的结果,这个可以通过枚举让每个因子都有卡上界者再减去没有选 \(1\) 的元素的容斥来得到答案,将每个质因子的贡献乘起来作为当前元素的结果

对于 \(\gcd\neq 1\) 的情况可以枚举 \(\gcd\) ,由于 \(\rm lcm\) 是其倍数,那么枚举复杂度就是调和级数

posted @ 2022-05-24 19:34  没学完四大礼包不改名  阅读(685)  评论(6)    收藏  举报