杂题乱写

· · 个人记录

CF734E Anton and Tree

一棵树的节点有黑白两种颜色,每次操作找到一个同种颜色的联通块,将它的颜色翻转,问将树操作至同色的最小操作次数

由于对一个点操作一次就可以将其周围的颜色相同的点全部变色,所以不难想到将相邻颜色相同的点缩成一个点

这样就能新建出来一棵邻点颜色不同的树

无论从哪个点开始变色,最优方案都是直接向外扩展变色,那么不难想到最优点应该在树的直径的中点上,这样向外扩展的点数和次数都是最多的

设新树上直径为 L,那么答案为 \lfloor\frac{L+1}{2}\rfloor

CF618E Robot Arm

考虑用线段树维护每条线段所对应的 向量(即终点和起点的相对位置)

由于向量可以平移,那么就先将所有线段的起点平移到原点,设平移后终点坐标为 (x,y)

对于操作 1,由相似,有:

\begin{cases}\frac{l}{\sqrt{x^2+y^2}}=\frac{\Delta x}{x} \\ \frac{l}{\sqrt{x^2+y^2}}=\frac{\Delta y}{y}\end{cases}\Rightarrow \begin{cases}\Delta x=\frac{lx}{\sqrt{x^2+y^2}} \\ \Delta y=\frac{ly}{\sqrt{x^2+y^2}}\end{cases}

所以直接将第 i 条线段的向量分别加上 \Delta x,\Delta y 即可,直接在线段树上单点修改

对于操作 2,先将给出的角度制转化为弧度制,设第 i 条线段原来相对于坐标轴的角度为 \theta,由三角恒等变换,有:

\begin{cases}x'=\sqrt{x^2+y^2}\cos(\theta-\alpha) \\ y'=\sqrt{x^2+y^2}\sin(\theta-\alpha)\end{cases}\Rightarrow \begin{cases}x'=x\cos\alpha+y\sin\alpha \\ y'=y\cos\alpha-x\sin\alpha\end{cases}

在线段树上打一个旋转角的 \text{lazy tag},对于第 i\sim n 条线段区间修改即可

由于向量可以平移,那么将每次操作后得到的线段重新收尾相接相对位置不变,且最后一条线段终点坐标为所有向量相加

每次答案即为线段树根节点的值

CF521D Shop

如果只考虑操作 3 的话,显然就是将值从大到小排序取前 m

这样可以考虑将操作 1,2 都转化为操作 3

有个贪心的想法就是操作一定是按 1,2,3 顺序来的

首先考虑操作 2

贪心地想也肯定是从大到小去选,所以也要排序

这样的话对于每一个位置的每个加法操作的前提都是这一个位置上再它之前的加法操作都被选了

即对于每个加法操作,都是把某个值为 x 的数变为一个值为 y 的数,其中 x 是这个数经过它前面的所有加法后变成的数,也就是一段前缀和

这样就可以直接把一个加法操作看成 \frac{x+y}{x} 的乘法操作

简单证明一下排在后面的加法,转化为乘法后肯定也没有之前优,即上述提到的 对于每一个位置的每个加法操作的前提都是这一个位置上再它之前的加法操作都被选了

a>b>c>d,要证明前面的乘法肯定要比后面的大,即:

\frac{c}{a+b}>\frac{d}{a+b+c}

移项,有:

c(a+b+c)>d(a+b)

显然成立

思考如果转化为乘法排序之后一个操作 2 再操作 3 之前了怎么办?

由于乘法是具有交换律的,因此可以把那些操作提到所有操作 3 之前,来满足第一开始说的贪心策略

接下来考虑操作 1

显然对于每个位置操作 1 最多用一遍,用多了显然没有意义

然后对于每个位置的操作 1\max 再转化为这个位置上的操作 2 进而转化到操作 3 即可

这个也不会打乱顺序进行 1,2,3 操作的贪心策略,理由同上

P4755 Beautiful Pair

挺套路的一道题,之前模拟赛考过两边这种套路

直接枚举最大值 a_i,看它所控制的区间 [l_i,r_i]

考虑启发式分裂,选取小的那段区间去枚举,设其为a_j,然后再另一边找小于等于 \frac{a_i}{a_j} 的数的个数即可

离散化之后直接建一棵主席树就行了

细节就是注意小数的取整和取整后它在离散化数组里的位置的问题

启发式分裂一个 \log,主席树一个 \log,时间复杂度是 O(n\log^2n)

为啥这么套路的题还写出来因为学到了这个东西叫启发式分裂

P4833 萨塔尼亚的一生之敌 / P3452 [POI2007]BIU-Offices

给定一张 n 个点 m 条边的图,求补图的连通块个数以及各个连通块的大小

有个 \text{naive} 的想法就是直接暴力建出补图然后去跑,但是这样边数是 n^2 级别的,显然会 \text{T}

发现只需要知道每个连通块的信息,所以可以考虑建出生成树

考虑 \text{BFS} 树,枚举一个没有被标记过的点 u 标记它并把它加入到队列,先把它在 原图 直接相邻的点标记,然后将它在 补图 上相邻且没有被标记过的点 v 标记并放入队列

可以直接用链表直接维护出来这个 v

这样每个点在链表中只会被遍历一遍,且这么做枚举仅涉及到树边,而对 u 枚举在原图上相邻的点也只等于枚举原图上的边的复杂度,所以总复杂度是 O(n+m)

P5307 [COCI2019] Mobitel

给定 r\times c 的矩形,每个格子有一个正整数,从左上角走到右下角每次向下或向右走,求路径上乘积不小于 n 的路径条数

有个 \text{naive}\text{DP} 就是设 f_{i,j,k} 为现在在 (i,j) 走过路径乘积为 k 的方案数

空间显然开不下

发现根本不在乎这个乘积是多少,在乎的是乘积是否 \geq n,所以可以更改定义,设 f_{i,j,k} 为现在在 (i,j),至少乘上 k 才能使乘积 \geq n 的方案数,有:

f_{i,j,\lceil\frac{k}{a_{i,j}}\rceil}\gets f_{i-1,j,k}+f_{i,j-1,k}

由整除分块的理论,\forall i\in[1,n],\lceil\frac{n}{i}\rceil 只有 O(\sqrt n) 种不同的取值,所以时间复杂度 O(rc\sqrt n)

将第三维离散化,第一维滚一下即可

CF1408H Rainbow Triples

给定一个长度为 n 的序列 p_{1\dots n},找出尽可能多的三元组 给定长度为 n 的序列 p,找出尽可能多的三元组 (a_i,b_i,c_i) 满足:

  • 1\leq a_i<b_i<c_i\leq n
  • p_{a_i}=p_{c_i}=0,p_{b_i}\not= 0
  • 所有的 a_i,b_i,c_i 互不相同

输出最多可以选出多少个三元组,多组数据

nb 题

z 为整个序列中 0 的个数,那么答案有个显然的上界为 \lfloor\frac{z}{2}\rfloor

考虑以第 \lfloor\frac{z}{2}\rfloor0 为界,将整个序列分为两个部分 L,R,那么 L 中右边的 0 个数 \geq\lfloor\frac{z}{2}\rfloorR 中左边的 0 的个数 \geq\lfloor\frac{z}{2}\rfloor

根据答案上界,L 中的数就无需考虑在它右边的 0,而只需考虑左边的 0R 中的数同理

如果 L,R 中有相同的数就选 L 中的最右边 / R 中的最左边作为这个数的代表进行匹配,感性理解这样匹配一定不会更劣

那么原问题就弱化为了: L 匹配位置左边的 0, R 匹配位置右边的 0,要求一个非 0 数只能和一个 0 配对,求最大匹配数

不难发现若这个弱化问题的答案 \geq\lfloor\frac{z}{2}\rfloor,那么对于原问题一定有一种方法使答案到达上界

对于弱化问题可以网络流求解:

源点 S 向每种颜色连一条流为 1 的边,对于 L 中的点向它的前一个点连一条流为 \inf 的边,对于 R 中的点向它的后一个点连一条流为 \inf 的边,对于 a_i=0i 向汇点 T 连一条流为 1 的边,对于一个颜色 a_i 向它在 L,R 中的最右边 / 最左边的位置连一条流为 1 的边

直接跑最大流和答案上界取 \min 即可

但是 n\leq5e5,暴力建图再跑显然会 \text{T} 飞,需要继续优化

由于最大流 = 最小割,所以可以考虑求解最小割

发现割去的边一定是一段前缀 0,一段后缀 0 和一些颜色边,所以只需要对于每个前缀 0 计算一下每个后缀 0 的最少割边即可

具体的话就是建一棵线段树,以割去的后缀 0 数量为下标,节点维护割去后缀 0 和颜色边的最小割边数量

对于一个颜色 x 若它没在 L 中出现那么就不用割颜色边,所以执行区间 -1

然后枚举割去多少前缀 0 的边,对于被割去的这个颜色 x,显然也不用去割颜色边,所以执行区间 -1

时间复杂度 O(n\log n)

P7054 [NWRRC2015]Graph / 2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest G Graph

给定一张 n 个点 m 条边的 \text{DAG},可以至多添加 k 条有向边,使得这仍然是一个 \text{DAG} 且字典序最小的拓扑序的字典序尽量大,输出这个拓扑序以及方案

如果没有加边操作那么直接用一个小根堆维护入度为 0 的点一个一个弹即可

考虑加边操作,对于现在的小根堆堆顶,一定是想要加一条边从而让它不出现在字典序的这一位,而又想在这个位置放一个字典序尽可能大的数

发现要加的这条边到底和谁连,可以暂时不关心

那么开一个小根堆 p 和一个大根堆 q 分别维护当前入度为 0 的点集和暂时加了一条边使它度数不为 0 的点集

尝试将 p 的堆顶放入 q

p 只有一个元素且堆顶字典序比 q 堆顶的字典序大,那么就将它作为这一位的答案

否则 k\gets k-1,将 p 的堆顶放入 q 中,直到 p 为空或 k=0

这样操作一轮之后,若 p 非空,说明不得不选择 p 的堆顶作为这一位的答案,否则这一位的答案就是 q 的堆顶,并从上一位的答案向 q 的堆顶连边

最后将当前答案的儿子入度全减一,若入度为 0 就扔到 p

[AGC014E] Blue and Red Tree

给定一棵 n 个节点的树,一开始所有边都是蓝色的,每次选择一条所有边都是蓝色的路径,删掉其中一条边,然后在路径的两个端点之间连一条红边,求最后能不能得到目标形态(都是红边)的树

将输入的红边看作对路径的覆盖,那么每次应该取的是只被覆盖一次的蓝边,这样不会对别的路径造成影响

那么做法就是找到被覆盖次数恰好为 1 的蓝边,以及覆盖它的路径,把路径经过的蓝边的被覆盖次数 -1

不断重复直到所有蓝边都被删去,若过程中出现没有被覆盖一次的蓝边就是不合法

用线段树维护,节点记录覆盖次数的最小值,这条边是哪条边和覆盖它的红边编号的异或和

维护异或和是因为这东西比较好删除,再异或回去就行了

CF1316F Battalion Strength

给定一个长度为 n 的序列 a_{1\dots n},定义一个序列的权值为原序列排序后相邻两项积的和,现在从中随机选取一个子序列,每个子序列被选到的概率相等,问取出的子序列的权值的期望时多少,动态带单点值修改

首先发现这个序列是假的,可以直接排序做来考虑两个数的贡献

两个数做出贡献当且仅当这两个数被选且它们中间没有数被选,所以答案为:

\sum\limits_{i=1}^{n}\sum\limits_{j=i+1}^{n}\frac{a_ia_j}{2^{j-i+1}}

然后这玩意要带修,考虑线段树,看它要维护点啥

若两段区间合并,那么有:

\limits_{i=l}^{mid}\frac{a_i}{2^{mid-i+1}})\times(\sum\limits_{j=mid+1}^{r}\frac{a_j}{2^{j-m}})\end{aligned}

pre_{l,r}=\sum\limits_{i=l}^{r}\frac{a_i}{2^{r-i+1}},suf_{l,r}=\sum\limits_{i=l}^{r}\frac{a_i}{2^{i-l+1}},用线段树再维护这两个值就可以 \text{pushup}

CF1580D Subsequence

给定一个长度为 n 的序列 a_{1\dots n},定义一个序列的价值为:

\sum\limits_{i= 1}^{m}(m\times a_{b_i})-\sum\limits_{i=1}^{m}\sum\limits_{j=1}^{m}f(\min\{b_i, b_j\}, \max\{b_i, b_j\})

其中 f(l,r)=\min\limits_{i=l}^{r}\{a_i\}

要从中选择一个长度为 m 的子序列,最大化选择子序列的价值

把式子拆一下,有:

(m-1)\sum\limits_{i=1}^{m}a_{b_i}-2\times\sum\limits_{i=1}^{m}\sum\limits_{j=i+1}^{m}f(b_i,b_j)

发现后面每个 b_i 正好被算了 m\times(m-1) 遍,所以能合到一起:

\sum\limits_{i=1}^{m}\sum\limits_{j=i+1}^{m}a_{b_i}+a_{b_j}+f(b_i,b_j)

发现这玩意很像树上两点间距离,于是把笛卡尔树建出来,每条边的权值是两个节点的权值差,答案就是选出 m 个点使两两的距离和最大,直接树上背包即可

P5643 [PKUWC2018]随机游走

给定一个起点 x,和一棵 n 个节点的树,多组询问,每个询问给定一个点集 S,求一个人从 x 随机游走,到达过 S 中的全部点期望时间

依旧考虑 \text{Min-Max} 容斥

不难想到把这道题的问题当做 \text{Max},那么设 \text{Min} 为到达点集 S 中第一个点的期望步数

f_{S,i} 表示从 i 出发到达 S 中的一个点的期望步数,有:

f_{S,i}=\begin{cases}0 & i\in S \\ \frac{1}{deg_i}(f_{S,fa_i}+\sum\limits_{v\in son_i}f_{S,v})+1 & i\notin S\end{cases}

一般是高斯消元来搞,但是这样做时间复杂度会爆炸,所以考虑线性递推

f_{S,i}=k_i\times f_{S,fa_i}+b_i,有:

\begin{aligned}f_{S,i}&=\frac{1}{deg_i}(f_{S,fa_i}+\sum\limits_{v\in son_i}(k_v\times f_{S,i}+b_v))+1 \\ deg_i\times f_{S,i}&=f_{S,fa_i}+sumk\times f_{S,i}+sumb+deg_i \\ f_{S,i}&=\frac{1}{deg_i-sumk}\times f_{S,fa_i}+\frac{sumb+deg_i}{deg_i-sumk}\end{aligned} \therefore\begin{cases}k_i=\frac{1}{deg_i-sumk} \\ b_i=\frac{sumb+deg_i}{deg_i-sumk}\end{cases}

然后就可以 O(n) 求了

g_T=(-1)^{|T|-1}f_{T,root},那么有:

ans=\sum\limits_{T\subseteq S,T\ne\varnothing}g_T

这是个或卷积,直接 \text{FWT}

时间复杂度 O(n2^n+q)

CF1137E Train Car Selection

给定一个初始有 n0 的序列 a_{1\dots n}m 次操作,操作有三种:

  • 在序列开头加 k0

  • 在序列末尾加 k0

  • 给序列的第 i 个位置加上 k(i-1)+b

每次操作过后输出当前序列中最小值位置和它的值,若存在多个最小值则只考虑位置最靠前的

首先不难发现每次加进去的一组 0 只需在意它们中的第一个

若在前面加一组 0 那么最小值永远就只会是第一个 0

考虑在后面加一组 0,若对于 x_i<x_j 有:

y_i+kx_i+b>y_j+kx_j+b

那么有:

k>\frac{y_i-y_j}{x_i-x_j}

所以维护一个左下凸包即可

对于操作 3 考虑记录两个变量 k,b 来表示每个点的值为储存的值加上标记的值

那么这个操作就是增加标记

可能操作完之后凸包会翘起来,再将翘起来的点删掉即可

要注意操作 1 清空的时候也要把标记清零,操作 2 为了让 y0 所以加入的点是 (n,-(kn+b))

CF1578L Labyrinth

给定一个 n 个点 m 条边的无向连通图,每条边有一个限制 w_i,每个点有一个权值 c_i,每到一个点可以选择是否将自己的体重加上点权,一旦体重超过边的限制就不能通过这条边,问最大的初始体重,使得从 1 号点出发且能吃掉所有糖果

不难发现走的路径一定在最大生成树上

然后发现它的走的策略是:对于当前树上最小的边,一定是先加完一边子树的所有权值,再走过这条边,再加完另外一边子树的所有权值

证明就是如果考虑一种走法使得从两边反复横跳加权值,那么则当前体重一定不超过当前树上最小的边,这样的话先加完一棵子树肯定是不劣的

建最大生成树的时候建出 \text{kruskal} 重构树,设 f_i 为以 i 为根的子树内当前最多可以多胖,使得可以加完这棵子树的权值,w 为虚点 i 的限制,sum_i 为子树权值和,有:

f_i=\max\limits_{u,v\in son_u}\{\min\{f_v-sum_u,w-sum_u\},\min\{f_u-sum_v,w-sum_v\}\}

CF1575M Managing Telephone Poles

给定一个 n\times m 的棋盘,有一些关键点,问每个点到最近关键点的距离和

先假设答案在左上方

lst_k 为表示第 k 列到在前 i 行中从上往下最后一个关键点,有:

\begin{aligned}S(i,j)&=\min\limits_{1\leq k\leq m}\{(lst_k-i)^2+(k-j)^2\} \\ &=\min\limits_{1\leq k\leq m}\{k^2-2jk+j^2+(lst_k-i)^2\}\end{aligned}

按照斜率优化的套路把它改写为:

k^2+(lst_k-i)^2=2jk+S(i,j)-j^2 \begin{cases}y=k^2+(lst_k-i)^1 \\ k=2j \\ x=k \\ b=S(i,j)-j^2\end{cases}

最小化截距,斜率单增,单调队列维护右下凸包即可

剩下的三个方向可以通过转坐标系来变成这种情况

CF338E Optimize!

给定一个长度为 n 的序列 a_{1\dots n} 和一个长度为 m 的序列 b_{1\dots m}(m\leq n),求有多少个 i\in[1,n-m+1] 使得 a_{i\dots i+m-1}b_{1\dots m} 能一一匹配,两个数 a,b 能匹配当且仅当 a+b\geq h

不难发现匹配一定是将 a_{i\dots i+m-1} 中最大的和 b_{1\dots m} 中最小的匹配,a_{i\dots i+m-1} 中次大的和 b_{1\dots m} 中次小的匹配,以此类推,这样一定不劣

那么问题可以转化为:对于 b_{1\dots m} 中的最大值,a_{i\dots i+m-1} 中至少有 m 个元素与其匹配,对于 b_{1\dots m} 中的次大值,a_{i\dots i+m-1} 中至少有 m-1 个元素与其匹配,以此类推

将序列 b 排序,对于序列 a 中的每一个元素,在 b 中二分找到第一个与其相加 \geq h 的元素并记录下标

那么问题变成了区间覆盖,询问序列 b 中第 i 大的元素是否被覆盖至少 i

将第 i 个位置的的值减去 i,那么又转化为了全局最小值是否 \geq 0

直接线段树维护即可

CF338D GCD Table

有一个 n\times m 的表,ij 列的值为 \gcd(i,j),给定一个序列 a_{1\dots k},问是否存在 x,y 使 \forall 1\leq i\leq k,\gcd(x,y+i-1)=a_i

由于 \gcd 可以内外除掉一个数,那么有:

\begin{cases}\gcd(x,y+1-1)=a_1 \\ \gcd(x,y+2-1)=a_2 \\ \gcd(x,y+3-1)=a_3 \\ \cdots \\ \gcd(x,y+k-1)=a_k\end{cases}\Rightarrow\begin{cases}\gcd(\frac{x}{a_1},\frac{y+1-1}{a_1})=1 \\ \gcd(\frac{x}{a_2},\frac{y+2-1}{a_2})=1 \\ \gcd(\frac{x}{a_3},\frac{y+3-1}{a_3})=1 \\ \cdots \\ \gcd(\frac{x}{a_k},\frac{y+k-1}{a_k})=1\end{cases}

发现 x 能整除所有 a_i,即 \text{lcm}\{a_i\}\mid x,那么最小的(不容易出界)合法的 x 就是 \text{lcm}\{a_i\}

同时还能发现 a_1\mid y,a_2\mid y+1,\dots,即:

y\equiv 1-i\pmod{a_i}

这是个同余方程组,直接 \text{exCRT} 合并即可

然后这样做只满足必要性不满足充分性,所以还要代回去验证

CF258D Little Elephant and Broken Sorting / AT4513 [AGC030D] Inversion Sum

给定一个长度为 n 的排列 p_{1\dots n},有 m 次操作,每次操作以 \frac{1}{2} 的概率执行交换 p_i,p_j,问 m 次操作之后逆序对的期望

由于期望具有线性性,所以可以考虑每一个位置对对答案的贡献最后加起来

f_{i,j}p_i>p_j 的期望,有:

\begin{cases}f_{i,x}=f_{i,y}=\frac{f_{i,x}+f_{i,y}}{2} \\ f_{x,i}=f_{y,i}=\frac{f_{x,i}+f_{y,i}}{2} \\ f_{x,y}=f_{y,x}=\frac{1}{2}\end{cases}

答案为:

\sum\limits_{i=1}^{n}\sum\limits_{j=i+1}^{n}f_{i,j}

P3349 [ZJOI2016]小星星

给出 n 个点 m 条边的无向图和一棵 n 个点的树,现需要给树上每个点 i 安排一个映射 a_i,满足对于树上任意边 (x,y),均有边 (a_x,a_y) 在给定的无向图中,要求 a 为一个排列,求方案数

有一个 \text{naive}\text{DP} 就是设 f_{i,j,S}i 映射到了 ji 的子树映射的状态为 S 的方案数

转移就枚举补集的子集转移,时间复杂度 O(n^33^n),用 size 卡紧再吸氧能获得 90pts 的好成绩

发现枚举子集咋样都优化不下去,所以可以考虑不枚举子集,用子集反演来搞

f_Sn 个点的映射恰好使用了 S 中的所有点的方案数,g_Sn 个点的映射至多使用 S 中的点的方案数,有:

g_S=\sum\limits_{T\subseteq S}f_T

由子集反演,有:

f_S=\sum\limits_{T\subseteq S}(-1)^{|S|-|T|}g_T

考虑计算 g,设 dp_{i,j,S} 为点 i 映射到了 ji 的子树至多使用了 S 中的点的方案数,有:

dp_{i,j,S}=\prod\limits_{v\in son_i}(\sum\limits_{k\in S,(j,k)\in E}dp_{v,k,S})

则:

g_S=\sum\limits_{j\in S}dp_{root,j,S}

时间复杂度 O(n^32^n)

P4865 Samcompu Loves Water

如果没有失效的跳转方式的话就将边从小到大排序,不断加边,方案数就是两个连通块大小相乘,用并查集维护一下即可

算答案就先离线按照时间排个序,若在加边前危险程度大于时间就直接把当前的总方案数 \times 2 当成答案

考虑加上失效的跳转方式

由于不同失效的跳转方式最多只有 10^3 种,所以将所有询问离线下来按照跳转方式分类,对每一种跳转方式都做一遍即可

CF1163F Indecisive Taxi Fee

给定一个 n 个点 m 条边的无向图,每条边有边权,有 q 次询问,每次询问给定一对 t,x,表示将 t 这条边的边权修改为 x,求 1\to n 的最短路长度,询问相互独立

首先跑一遍 \text{Dijkstra} 求出 1\to n 的最短路并标记,分类讨论一下:

后三种都很好写,直接 O(1) 出解就行了

考虑第一种情况,发现答案就是

\min\{\text{原最短路长度-原边权+新边权,不经过修改的这条边的最短路长度)}\}

现在就是要求出不经过某条边的最短路长度

对于一个不在原最短路上的边 (u,v),经过这条边的最短路径一定是走一段原最短路的前缀,走这条边,再走一段原最短路的后缀

L_u,R_u 分别为原最短路上连接 u 的边的编号和 u 连到下一个原最短路上点的边的编号

维护一棵线段树,下标为原最短路上边的编号,值为不经过这条边的最短路长度

枚举每一个不在原最短路上的边更新即可

CF431D Random Task

f(n)=\{n,n+1,\dots,2n\},g(n)=\sum\limits_{i\in f(n)}[\text{popcount}(i)=k]

由于 f(n)-f(n-1)=\{2n,2n-1\}-\{n\},而 \text{popcount}(n)=\text{popcount}(2n),所以 g(n) 单调不降

所以可以二分,数位 \text{DP} 计算 g(n)

P3544 [POI2012]BEZ-Minimalist Security

给定一张 n 个点 m 条边的无向图,每个点有点权,每条边有边权,满足点权和边权都非负,且每条边的权值小于等于两个顶点的权值和,现在要将每个点减一个数,满足非负且小于等于点权,使得每条边权等于两个顶点的点权和,问最大修改代价和最小修改代价

val_i 为点权,z_i 为减去的代价,w(u,v) 为边权,根据题意能列出来这个式子:

val_u-z_u+val_v-z_v=w(u,v)

将式子移项,有:

z_u+z_v=val_u+val_v-w(u,v)

等号右边这一串式子是个定值,所以只要确定了一个点 i 的代价 z_i,那么和 i 点在同一个连通块的点 j 的代价 z_j 都能确定,且都能用 k_j\times z_i+b_j 来表示

那么一个连通块的答案为 z_i\times \sum\limits_{j=1}^{n}k_j+\sum\limits_{j=1}^{n}b_j

具体做法是将连通块内任意一点代价设为 z,然后 \text{BFS} 遍历整个连通块

如果没有访问过当前点,那么就用 z 来表示当前点的代价

如果已经访问过当前点,那么联立解方程组,判断有解,无解和无数解

AT2705 [AGC019F] Yes or No

不难想到最优策略是哪个多就选哪个

画一个坐标系,横坐标表示未猜 yes 的数量,纵坐标表示未猜 no 的数量

(n,m) 出发,若现在在 y=x 的下方,那么肯定往左走,若现在在 y=x 的上方,那么肯定往上走

首先一定能猜中 \max\{n,m\} 个,现在只需要考虑在 y=x 上时能猜中几个

由于期望的线性性,考虑每个在 y=x 上的点的贡献

经过一个点的方案数为 \binom{2i}{i}\binom{n+m-2i}{n-i},总方案数为 \binom{n+m}{n},有 \frac{1}{2} 的概率猜对,所以所有在 y=x 上的直线的点的贡献为:

\sum\limits_{i=1}^{\min\{n,m\}}\frac{\binom{2i}{i}\binom{n+m-2i}{n-i}}{2\binom{n+m}{n}}

最后再把稳了的 \max\{n,m\} 加上即可

CF1503E 2-Coloring

盗个图

不难发现合法的染色方式都如上图所示

然后就是要数这个玩意

可以枚举一个峰的高度和两个峰的位置来计算,其中设 A 为第一个峰最靠下的点,B 为第二个峰最考上的点,强制第一个峰在上面,有:

2\sum\limits_{i=1}^{n-1}\sum\limits_{j=1}^{m-1}\sum\limits_{k=j+1}^{m}\binom{j+i-1}{i}\binom{m-j+i-1}{i-1}\binom{k+n-i-1}{n-i-1}\binom{m-k+n-i-1}{n-i}

其实就是数路径,第一个组合数是从左上走到 A,强制最后一步向下走的方案数

第二个组合数是从 A 的下一个位置走到左下的方案数,剩下两个组合数同理

然后因为强制了,所以最后 \times 2

这个直接算是 O(nm^2) 的,但是可以提一下:

2\sum\limits_{i=1}^{n-1}(\sum\limits_{j=1}^{m-1}\binom{j+i-1}{i}\binom{m-j+i-1}{i-1})(\sum\limits_{k=j+1}^{m}\binom{k+n-i-1}{n-i-1}\binom{m-k+n-i-1}{n-i})

可以用前缀和优化到 O(nm)

数蓝色的话就将 n,m 互换一下即可,但是这样蓝黄连通块个数都是 2 的情况会被算重,因此第二次计算的时候需要强制令 k-j\geq 1

[AGC013E] Placing Squares

给定一个长度为 n 的木板,在若干整数位置断开将它分为若干段,要求其中 m 个位置不能成为断点(称为标记点),定义一种划分方案的贡献为最终所有线段长度乘积的平方,求所有方案贡献之和

组合意义天地灭,代数推导保平安

f_i 为考虑前 i 个格子并在 ii+1 放隔板的方案数,显然有:

f_i=\begin{cases}\sum\limits_{j=0}^{i-1}f_j\times(i-j)^2 & \text{i is a markpoint} \\ 0 & \text{i is not a markpoint}\end{cases}

考虑优化,假设 i+1 不是标记点,那么有:

\begin{aligned}f_{i+1}&=\sum\limits_{j=0}^{i}f_j\times(i+1-j)^2 \\ &=\sum\limits_{j=0}^{i-1}f_j\times(i+1-j)^2+f_i \\ &=\sum\limits_{j=0}^{i-1}f_j\times(i-j)^2+2\sum\limits_{j=0}^{i-1}f_j\times(i-j)+\sum\limits_{j=0}^{i-1}f_j+f_i\end{aligned}

a_i=\sum\limits_{j=0}^{i-1}f_j,b_i=\sum\limits_{j=0}^{i-1}f_j\times(i-j),c_i=\sum\limits_{j=0}^{i-1}f_j\times(i-j)^2,有:

\begin{cases}f_i=c_i \\ f_{i+1}=a_i+2b_i+c_i\end{cases}

假设已经知道了 a_i,b_i,c_i,只需能求出 a_{i+1},b_{i+1},c_{i+1} 就能实现方程的转移,分类讨论一下:

显然可以矩阵快速幂优化,那么是不是关键点的转移矩阵分别为 \begin{bmatrix}1 & 0 & 0 \\ 1 & 1 & 0 \\ 1 & 2 & 1\end{bmatrix}\begin{bmatrix}1 & 0 & 1 \\ 1 & 1 & 1 \\ 1 & 2 & 1\end{bmatrix}

P4900 食堂

多组询问,求:

\sum\limits_{i=A}^{B}\sum\limits_{j=1}^{i}\{\frac{i}{j}\}\pmod{998244353}

其中 \{\} 表示取小数部分

转化一下,题目就是要求:

\sum\limits_{i=A}^{B}\sum\limits_{j=1}^{i}\frac{i}{j}-\sum\limits_{i=A}^{B}\sum\limits_{j=1}^{i}\lfloor\frac{i}{j}\rfloor\pmod{998244353}

前一部分就是求:

\sum\limits_{i=A}^{B}\sum\limits_{j=1}^{i}i\times\text{inv}(j)\pmod{998244353}

f(i)=i\times\sum\limits_{j=1}^{i}\text{inv}(j),那么就是先对逆元求前缀和,再对 f 求前缀和

对于后一部分考虑 \lfloor\frac{i}{j}\rfloor 的更多的含义

其实等同于求出小于等于 i 的数中有多少个数是 j 的倍数

扩展到求和就是求小于等于 i 的数中有多少是 1 的倍数,2 的倍数,3 的倍数,\dots i 的倍数

也就是说,对于每一个数,它对这个答案的贡献就是它的因子个数

那么直接线性筛约数个数即可

[AGC010F] Tree Game

先考虑简单的情况:

假设棋子放在 1 上,那么先手只能往 2 走,而后手也只能往 1 走,那么先手必胜当且仅当 a_1>a_2

将情况变难一下:

假设棋子放在 1 上,那么先手必然向某个叶子走,而后手只能将棋子移回 1,显然先手将棋子移动到 a_i 小的叶子是最优的,那么先手必胜当且仅当 a_1>\min\{a_i\}

将情况再变难:

假设棋子放在 1 上,那么先手会将棋子移动到 2\sim 6 的某个点上

假设在 4 的子树内,4 是先手必胜的,那么 1 一定不会去往 4 走,因为一旦走到,那么后手就有了必胜策略

假设 4 是后手必胜的,那么 14 走后,后手一定会返回 1,因为继续往下走的话先手就有了必胜策略

这样就回到了上一张图所讨论的情况,此时先手必胜当且仅当 a_1>\min\{a_i\}

那么做法就是枚举所有点作为根,\text{DFS} 处理每个点儿子的情况,然后判断该点的胜负状况