2023.01.13 题目选讲 学习笔记

讲课人:周航锐。

WC2023 Day1 下午的课。

1.P8494 [IOI2022] 最罕见的昆虫

首先不断做 \(1\) 操作,每做完一次 \(1\) 操作后做一次 \(3\) 操作,如果查询结果 \(>1\) 则对刚加入的那只虫子做 \(2\) 操作,这样每种操作花费不超过 \(N\) 次就可以知道不同昆虫种数 \(k\)。现在知道答案在 \([1,\lfloor\frac{N}{k}\rfloor]\) 中,同时需要查询的昆虫数为 \(N\) 只。

假设答案在 \([l,r]\) 中,需要查询的昆虫数为 \((r-l+1)k\) 只(可能会有常数上的差异)。考虑二分一个 \(mid=\frac{l+r}{2}\),不断做 \(1\) 操作,每做完一次 \(1\) 操作后做一次 \(3\) 操作,如果查询结果 \(>mid-l+1\) 则对刚加入的那只虫子做 \(2\) 操作。容易知道都做完后已加入的虫子数不超过 \((mid-l+1)k\),现在再判断是否等于 \((mid-l+1)k\),如果等于那令 \(l=mid+1\),并且之后不再考虑这 \((mid-l+1)k\) 只昆虫;如果小于 \((mid-l+1)k\),那么令 \(r=mid\),把没加入的昆虫都丢掉,只留下容器内的昆虫。可以发现两种情况剩余昆虫数不超过区间长度乘 \(k\),于是操作次数 \(T(N)=N+\max\left(T(\lfloor\frac{N}{2}\rfloor),T(\lceil\frac{N}{2}\rceil)\right)\),即 \(T(N)=2N+C\)\(C\) 是一个常数,随机化加剪剪枝就可以了。

时间复杂度 \(O(N)\),空间复杂度 \(O(N)\)

2.Gym104065E Hammer to Fall

\(f_{i,j}\) 表示第 \(i\) 次袭击后,在点 \(j\) 至少还要行走多少距离才能存活。转移就是如果第 \(i\) 次袭击不是 \(j\),那 \(f_{i-1,j}=f_{i,j}\),否则 \(j\) 只会走一条边到一个相邻节点上,即 \(f_{i-1,j}=\min_{(j,v)\in G}f_{i,v}+w(j,v)\)\(w(j,v)\) 表示 \((j,v)\) 这条边的权值。对出度以 \(B\) 为阈值进行分治,如果出度 \(\le B\) 直接 \(O(B)\) 暴力更新,如果出度 \(>B\) 那每个点最多和 \(\frac{m}{B}\) 个出度 \(>B\) 的点相邻,对每个出度 \(>B\) 的点维护个 multiset(也可用优先队列实现),一个点更新后在能到达其的所有出度 \(>B\) 的点的 multiset 里删除旧答案并插入新答案,即可实现单次 \(O(\log n)\) 更新。

时间复杂度 \(O(n+m+q(B+\frac{m}{B}\log n))\),平衡复杂度得最终时间复杂度为 \(O(n+m+q\sqrt{m\log n})\),空间复杂度 \(O(n+m)\)

3.CF1707D Partial Virtual Trees

设原题要求的东西在 \(k\) 时的答案为 \(f_k\),把 \(\subsetneq\) 改成 \(\subseteq\) 而其它条件不变的答案为 \(g_k\)

\(\subsetneq\) 等于 \(\subseteq\) 减去 \(=\) 来容斥,如果在一个确定 \(k\) 的方案中有 \(l\) 个等号,容斥系数就是 \((-1)^l\),而有 \(l\) 个等号的情况有 \(\binom{k}{l}\) 种,所以 \(f_k=\sum_{l=0}^{k}(-1)^l\binom{k}{l}g_{k-l}\)。这可以 \(O(n^2)\) 求。

\(dp_{i,j}\) 表示以 \(i\) 为根的子树中,经过了 \(j\) 次从一个点集中选出一个子集的过程后变为 \(\{1\}\) 的方案数。考虑 \(i\) 什么时候能从点集中删去,当且仅当其所有子树都被删空或者还剩一个子树,枚举 \(i\) 删除的时间得到转移 \(dp_{i,j}=\sum_{k=1}^{j}\left(\prod_{v\in son_i}dp_{v,k}\right)\left(1+\sum_{v\in son_i}\frac{dp_{v,j}-dp_{v,k}}{dp_{v,k}}\right)\),可以维护前缀积和后缀积优化至 \(O(n^2)\)

总时间复杂度 \(O(n^2)\),空间复杂度 \(O(n^2)\)

4.Gym102769D Defend City

我们用 \(1,2,3,4\) 代表向右上、向左上、向左下、向右下这四个方向,\(P_i\) 表示 \(i\) 方向的点集,\(Q_i\) 表示从 \(P_i\) 中选出的集合。显然对每个 \(P_i\) 如果内部存在两个点是包含关系则可以删掉被包含的点,这样每个 \(P_i\) 里的点随着 \(x\) 的递增,\(y\) 都是递减的。

一个结论是在最优方案中 \(|Q_1|=|Q_3|=1\)\(|Q_2|=|Q_4|=1\)。若某个 \(Q_i\ge 2\),不妨设为 \(Q_3\),从 \(Q_3\) 中选取两个相邻的点,它们的覆盖范围会有一个交点,考虑这个交点往右上一点点的位置是被什么方向的点覆盖的,由于选的两个点是相邻的所以不可能是 \(3\),如果是 \(2\)\(4\) 那这两个相邻的点只需选一个仍能覆盖相同区域,所以只可能是 \(1\)。这个 \(1\) 的点覆盖了至少两个 \(3\) 的点,并且只会恰好覆盖两个 \(3\) 的点。所以单看 \(1\)\(3\) 的点最后是长这样的:

那么左上的 \(2\) 的点只要能覆盖到 \(1\) 的轮廓线和 \(3\) 的轮廓线的左上方的交点即可,右下同理,故 \(Q_2\)\(Q_4\) 在此情况下都只会有一个点。

不妨设最优答案中 \(|Q_2|=|Q_4|=1\)。枚举 \(Q_1\) 中选的最靠上的点 \(a\),之后确定 \(Q_2\) 中的点 \(b\)\(Q_3\) 中最靠上的点 \(c\),由于 \(b\) 中的覆盖区域一定要包含 \(a\)\(c\) 覆盖区域左上的交点 \(x\),并且 \(x\) 是在 \(a\) 的左边界上,在此基础上我们想让右下的区域尽可能小,而 \(a\) 的下边界不会变,也就是要让 \(c\) 的右边界尽量右,即让 \(b\) 的下边界尽量下,所以 \(b\) 是右边界在 \(a\) 的左边界右方(含,下都是含)的最靠左点,\(c\) 是上边界在 \(b\) 的下边界上方的最靠下的点,之后不断贪心地轮流选 \(Q_1,Q_3\) 中的点,直至右下的区域可被 \(Q_4\) 中的点覆盖。发现前三步确定后之后每步只和前一步选了哪个点有关,可以倍增优化到 \(O(n\log n)\)

可以发现前三步选完后再选一个 \(Q_1\) 中的点 \(d\) 那么 \(a\) 就没用了,此时 \(c\) 越靠右 \(d\) 也越靠下,也就是说在答案至少为 \(5\) 的情况下,\(a\) 并不会对后面造成影响,而只需让 \(c\) 最靠右,即让 \(c\) 的上边界最靠下,而 \(c\) 的上边界必须在 \(a\) 的下边界(为了与 \(a\) 有交点)和 \(b\) 的下边界(为了交点被 \(b\) 包含)之上,所以前两个点 \(a,b\) 需让它们俩更靠上的下边界尽量的下,可以发现此时选的 \(a\) 一定是在 \(P_1\)\(P_2\) 的轮廓线交点的下方或左方的那个点(取决于轮廓线相交的方向),也就是说不用再枚举 \(a\) 了,之后直接贪心即可。注意要特判掉答案为 \(4\) 的情况(直接枚举 \(a\),确定 \(b,c\),看 \(P_4\) 中是否有矩形能直接覆盖剩余区域)。

时间复杂度 \(O(n)\),空间复杂度 \(O(n)\)

5.QOJ#4815. Flower’s Land

如果连通块必须包含根节点,那么一个点被选可知其祖先也都被选,一个点没选可知其子树都没选,设 \(dp_{i,j}\) 表示 DFS 到 DFS 序为 \(i\) 的点,目前已经选的点数为 \(j\),转移看 DFS 序为 \(i\) 的点是否选即可 \(O(1)\) 转移。

考虑点分治,如果连通块内点数 \(<k\) 就返回,时间复杂度是 \(O(nk\log(\frac{n}{k}))\) 的,空间复杂度 \(O(nk)\)

6.QOJ#4812. Counting Sequence

\(m\le\sqrt{2n}-O(1)\),那么不会用到 \(a_i>0\) 这个条件,否则总和就凑不到 \(n\) 了。设 \(dp_{i,j}\) 表示第一个数是 \(0\)、已经确定了 \(i\) 个数、和为 \(j\) 的贡献之和,转移考虑在 \(i\) 个数前加一个 \(0\),且 \(i\) 个数同时加上 \(1\)\(-1\) 即可 \(O(1)\) 转移。之后枚举 \(m\),再枚举首项 \(a_1\),答案就是 \(f_{m,n-ma_1}\)。若 \(m>\sqrt{2n}-O(1)\),则最大数是 \(O(\sqrt{n})\) 级别的,否则总和会超过 \(n\)。设 \(dp_{i,j}\) 表示总和为 \(i\),最后一个数是 \(j\) 的贡献之和,转移枚举下一个数与最后一个数的差也是 \(O(1)\) 的。

总时间复杂度 \(O(n\sqrt n)\),空间复杂度 \(O(n\sqrt n)\)

7.LOJ#3362. 「JOI Open 2020」黑白点

首先最优方案中不会有这种结构,不然调整两个黑点匹配的白点会严格优:

然后这可以推出一个结论\(^{(1)}\):如果把所有白点、黑点都顺时针依次标号为 \(0\sim n-1\),假设第 \(i\) 个白点匹配第 \(j\) 个黑点,那么第 \((i+1)\bmod n\) 个白点一定匹配第 \((j+1)\bmod n\) 个黑点。

对于第 \(i\) 个白点和第 \(j\) 个黑点连的这条线,假设把圆分成的两段,一段有 \(a_1\) 个白点 \(b_1\) 个黑点,另一段有 \(a_2\) 个白点 \(b_2\) 个黑点,\(a_1+a_2=b_1+b_2=n-1\),那么与这条线相交的线最多有 \(\min(a_1,b_2)+\min(a_2,b_1)=\min(a_1+a_2,b_2+a_2,a_1+b_1,b_2+b_1)=\min(\min(a_1+b_1,b_2+a_2),n-1)=\min(a_1+b_1,b_2+a_2)\),也就是这条线两边点数少的那边的点数。这是上界,并且根据我们的匹配方案上界是能取到的,所以可以枚举 \(0\) 号白点和哪个黑点匹配,答案可以用前缀和优化一起计算。

时间复杂度 \(O(n)\),空间复杂度 \(O(n)\)

\((1)\) 证明:

若结论不成立,即存在第 \(i\) 个白点匹配第 \(j\) 个黑点,而第 \((i+1)\bmod n\) 个白点不匹配第 \((j+1)\bmod n\) 个黑点。

\(0\) 表示 \(i\) 号白点,\(1\) 表示 \(j\) 号黑点,\(2\) 表示 \((i+1)\bmod n\) 号白点,\(3\) 表示 \((j+1)\bmod n\) 号黑点,\(4\) 表示 \((i+1)\bmod n\) 号白点匹配的黑点,\(5\) 表示 \((j+1)\bmod n\) 号黑点匹配的白点。我们证明单看这六个点就一定会出现上图中不优的结构。

既然只看这六个点,那么我们只在乎这六个点在圆上的相对位置,可以顺时针枚举六个点在圆上的相对位置。限制条件有:1. \(0\) 顺时针到 \(2\) 之间不会有 \(5\)\(1\) 顺时针到 \(3\) 之间不会有 \(4\)。2. \((0,1),(2,4),(3,5)\) 这三条线两两之间不能形成上述不优的结构。

写一份代码把所有情况都跑完后发现在上述假设和限制条件下确实没有合法情况,推出矛盾,所以原命题得证。代码如下:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int tot=0;
int p[6],to[6];
inline bool check1(int x,int y,int z)
{
	for(int i=to[x];i!=to[y];(++i)%=6)if(p[i]==z)return 1;
	return 0;
}
inline bool check2(int x,int y,int z,int w)
{
	if(to[x]>to[y])swap(x,y);
	if(to[z]>to[w])swap(z,w);
	if(to[x]>to[z])swap(x,z),swap(y,w);
	if(to[x]<to[z] && to[z]<to[y] && to[y]<to[w])return 0;
	return 1;
}
inline void check()
{
	if(check1(0,2,5))return ;
	if(check1(1,3,4))return ;
	if(check2(0,1,2,4))return ;
	if(check2(0,1,3,5))return ;
	if(check2(2,4,3,5))return ;
	printf("%d:",++tot);for(int i=0;i<6;++i)printf("%d%c",p[i],i==5? '\n':' ');
}
inline void dfs(int x)
{
	if(x>=6)return check();
	for(int i=0;i<6;++i)if(!(~to[i]))to[p[x]=i]=x,dfs(x+1),to[i]=-1;
}
int main()
{
	memset(to,-1,sizeof(to)),dfs(0);
	return 0;
}

8.Gym104076L Tree Distance

点分治,每个点作为分治中心时控制的范围是一个连通块,连通块内每个点的权值设为该点到分治中心的距离,查询 \([l,r]\) 相当于在每个连通块中取出编号在 \([l,r]\) 间的权值最小的两个点(两个点如果在同一子树内并不会更优)。但这样一个询问最多会被下放到 \(O(n)\) 个分治中心处查询。

对于一个连通块,将所有点按编号从小到大排序,依次枚举某个点 \(x\) 的权值是次小值,找到可能成为最小值的点。只需往 \(x\) 左右各找到第一个权值比 \(x\) 小的点,原因是如果左边有两个点 \(y<z<x\) 满足 \(y,z\) 权值都比 \(x\) 小,那选 \((y,z)\) 一定比 \((x,y)\) 优。所以一个长度为 \(l\) 的序列我们提取出了 \(2l\) 对可能成为答案的点对。

继续点分治,点分治时考虑在点分树上深度相同的点,一共有 \(O(\log n)\) 层。每一层,可以提取出 \(2n\) 对可能成为答案的点对,形如 \((l,r,v)\),表示 \(l\) 号点和 \(r\) 号点的路径长为 \(v\)(或者说不超过 \(v\)),共有 \(O(n\log n)\) 个三元组。查询有 \(q\) 个形如 \([L,R]\),表示查询 \(O(n\log n)\) 个三元组中 \(L\le l\le r\le R\)\(v\) 的最小值,可以对三元组和查询的右端点扫描线,维护一棵线段树表示当前扫到的位置为右端点的情况下每个点作为左端点的答案,扫到三元组就前缀取 \(\min\),扫到查询就单点查询即可。

时间复杂度 \(O(n\log^2n+q\log n)\),空间复杂度 \(O(q+n\log n)\)

9.UOJ#751. 【UNR #6】神隐

一种方法是考虑边的编号的每一位,把该位为 \(0\) 的边问一次,该位为 \(1\) 的边问一次,两个点 \(x,y\) 在某次询问中在同一集合说明它们路径上的所有边的这一位都一样(并且知道是 \(0\) 还是 \(1\)),两个点相邻当且仅当在 \(2\log n\) 次询问中恰好有 \(\log n\) 次在同一集合。枚举两个点判断是否相邻,询问次数 \(2\log n\),时间复杂度 \(O(n^2\log n)\)

将边用 \(2m\) 位且 \(0,1\) 各占 \(m\) 位的 \(01\) 串重编号,取 \(m=10\)\(\binom{2m}{m}>131702\) 编号足够,依次把每位为 \(1\) 的边问一次,两个点 \(x,y\) 在某次询问中在同一集合说明它们路径上的所有边的这一位都为 \(1\),两个点相邻当且仅当在 \(2m\) 次询问中恰好有 \(m\) 次在同一集合。枚举两个点判断是否相邻,询问次数 \(2m\),时间复杂度 \(O(n^2\log n)\)

如何减小时间复杂度?在后者方法中若某次询问一个点在孤立集合(只有该点的集合)中,则与该点相邻的所有边该位都为 \(0\),所以一个点是叶子等价于在 \(2m\) 次询问中恰好有 \(m\) 次该点在孤立集合中。每次删去一个叶子,并把叶子从 \(2m\) 次询问得到的集合中删去,可以得到原树的一个剥叶子序。按剥叶子序倒着加入,每次加入一个叶子,只要快速找到其父亲就好了。加入叶子时所在 \(2m\) 个集合中有 \(m\) 个集合不为孤立集合,其父亲一定在这 \(m\) 个集合中都出现过。在这 \(m\) 个集合中,每个集合内剥叶子序最大(也就是最早被加入的点)一定是该点父亲到根的链上的点,同时这些点也一定包含该点的父亲,取最晚被加入的那个点就是该点的父亲。

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

10.Gym104128L Proposition Composition

一个结论是:让初始时所有边边权都为 \(0\),给第 \(i\) 次加入的边以及该边在链上覆盖的边的权值全加上 \(2^i\),则删掉的两条边满足条件当且仅当至少有一条边权值为 \(0\) 或两条边权值相等\(^{(1)}\)。前者是好算的,对于后者,我们把所有权值相同的边组成的集合称作等价类,那么一个大小为 \(x\) 的等价类对答案的贡献就是 \(\binom{x}{2}\)

用线段树维护边权,如果已知某一时刻所有边的边权,可以在 \(O(\log n)\) 时间内推出上一时刻或下一时刻所有边的边权。这样可以在 \(O(n\log n)\) 时间内求出最终所有边的边权。

可以发现,如果某一时刻两条边在同一等价类中,那之前也一定都在同一等价类中;反之,如果某一时刻两条边不在同一等价类中,那之后也一定都不在同一等价类中。也就是说,随着时间的推移,一些等价类逐渐分裂成几个等价类。这启发我们分治,分治到区间 \([l,r]\) 时你已知 \(l\) 时刻所有等价类集合、\(r\) 时刻所有等价类集合、每个 \(r\) 时刻等价类集合是由哪个 \(l\) 时刻等价类集合分裂得到的。为了保证时间复杂度,我们尝试让每个区间的信息量在该区间内分裂次数的级别,这样总的信息量就是 \(O(n\log n)\) 的。维护一个指针指向某个时刻,同时维护该时刻所有边权值组成的线段树,让每次递归和离开一个区间 \([l,r]\) 时指针在 \(l\),之后移到 \(mid\) 求出中间时刻的信息,在递归 \([mid,r]\) 后把指针移回 \(l\),这样指针总移动距离是 \(O(n\log n)\) 的,这部分的时间复杂度为 \(O(n\log^2 n)\)

现在有了 \(mid\) 时刻维护的线段树,在 \(r\) 时刻每个等价类中任取一条边并在线段树上查询,可以知道每个 \(r\) 时刻的等价类是从哪个 \(mid\) 时刻的等价类分裂过去的。再在 \(mid\) 时刻每个等价类中任取一条边并在线段树上查询,可以知道每个 \(mid\) 时刻的等价类是由哪个 \(l\) 时刻的等价类分裂而来的。现在还要通过一些处理使得递归进 \([l,mid],[mid,r]\) 时信息量在对应区间内分裂次数的级别。对于区间 \([l,r]\),如果某个在 \(l\) 时的等价类到 \(r\) 时没有分裂还是一个等价类,那么在 \([l,r]\) 的任意时刻它都不会变化,可以直接把 \([l,r]\) 时刻的答案都加上这个等价类的贡献,之后就可以不管这个等价类了。这样区间 \([l,r]\) 左侧剩余的等价类在经过 \([l,r]\) 后都会分裂,每次分裂只会多产生一个等价类,信息量就正确了。对于每个信息,它在线段树上查询了 \(O(1)\) 次,所以这部分的时间复杂度也为 \(O(n\log^2 n)\)

总时间复杂度 \(O(n\log^2 n)\),空间复杂度 \(O(n\log n)\)

\((1)\) 证明:

我们证明不止是在链上,甚至在树上做同样的操作也是对的。证明分为两部分,先证明满足条件的边删去后必然不连通,再证明不满足条件的边删去后一定连通。

第一部分:如果某条边是 \(0\),那么它就是割边。如果两条边都不是 \(0\),且其中有非树边,可以发现只能有恰好一条非树边,那么把非树边删掉,在树上覆盖的边的权值都减去该非树边的权值,要删的另一条边权值就变 \(0\) 了;否则,两条边都是树边,我们把原树分成只考虑除这两条树边外的树边形成的三个连通块,如下图。对于每条跨过左边的树边的非树边,其也一定跨过右边的树边,所以 \(2\)\(1,3\) 一定不连通。

第二部分:如果两条边都是非树边,显然仍连通;如果恰有一条是非树边,那么把非树边删掉,在树上覆盖的边的权值都减去该非树边的权值,要删的另一条树边权值不为 \(0\),把原树分成只考虑除这条树边外的树边形成的两个连通块,按照定义一定有一条边跨过该树边连接这两个连通块;否则,两条边都是树边,我们把原树分成只考虑除这两条树边外的树边形成的三个连通块,如上图。如果没有同时跨过左右两条树边的边,结合两条边权值都不为 \(0\) 可知一定有至少一条边连接 \(1,2\),至少一条边连接 \(2,3\);否则,\(1,3\) 一定连通,结合两条边权值不同可知一定还有至少一条非树边只跨过左边或右边的树边,那么 \(2\) 也和 \(1,3\) 连通了。

11.CF1761F2 Anti-median (Hard Version)

考虑 \(m=1\) 时的限制,可以推出相邻三个数的大小呈单峰或单谷,进而推出所有偶数位置的数都比相邻奇数位置的数大或所有奇数位置的数都比相邻偶数位置的数小。不妨只考虑前者。

考虑 \(m=2\) 时的限制,如果最中间的位置是偶数,那它已经比相邻两个奇数位置的数大了,此时不能比剩余两个偶数位置的数都小,即相邻三个偶数位置的数是递增、递减或单峰的,于是所有偶数位置的数就是单峰的;同理所有奇数位置的数就是单谷的。

比较神奇的是,只考虑上面两个限制,\(m\ge 3\) 时的限制一定会满足。如果 \(m\ge 3\) 时最中间的位置是偶数,它一定会比左右其中一边的 \(\lfloor\frac{m}{2}\rfloor\) 个偶数位置的数都大(因为单峰),不妨设比左边都大,这 \(\lfloor\frac{m}{2}\rfloor\) 个数又会比自己左边相邻的奇数位置的数大,再加上中间那个数比相邻两个奇数位置的数都大,它已经比 \(2\lfloor\frac{m}{2}\rfloor+2\) 个数大了,自然不会是区间中位数。最中间的位置是奇数同理。

假设 \([1,n]\) 中最大的偶数是 \(mx_0\),最大的奇数是 \(mx_1\),把所有数重新排列在一个环上,按照 \(p_{mx_0},\cdots,p_{2},p_{1},\cdots,p_{mx_1}\) 的顺序逆时针排列(如下图)并依次编号为 \(0\sim n-1\),注意这是在环上所以首尾相接。注意到 \(p_{mx_0},\cdots,p_{2}\) 是单峰的,\(p_{1},\cdots,p_{mx_1}\) 是单谷的,\(p_2\)\(p_1\) 大,\(p_{mx_0}\)\(p_{mx_1}\) 大,所以任意 \(k\) 个最小的数在环上一定是一段连续的区间。

于是可以 dp 了,设 \(dp_{i,j}\) 表示环上已填的最小的数在环上是从 \(i\) 逆时针到 \(j\) 这一段区间,转移考虑下一个数填左边还是右边,初始给定的部分 \(p\) 也可以在 dp 的过程判断。注意直接这样 dp 只满足了 \(m=2\) 时的限制,\(m=1\) 时的限制也要在 dp 中判断。时间复杂度是 \(O(n^2)\) 的,可以通过 F1。

继续考察 dp 的性质。假设初始时没有给定 \(p\)(给定的 \(p\) 全为 \(-1\)),那么在 dp 的过程中只需要判断 \(m=1\) 时的限制。如果枚举了起始点(填 \(1\) 的位置)和 dp 的终止状态,我们把起始点对应到平面直角坐标系的 \((0,0)\),向左、向右填数分别看成在坐标系上向上、向右走一步,最终状态是固定的。在填数的过程中,不满足 \(m=1\) 的限制可能是奇数位中已经填的数的前缀比偶数位短了(如下图红色,可能有 \(O(1)\) 的误差),或者奇数位中已经填的数的后缀比偶数位短了(如下图蓝色,可能有 \(O(1)\) 的误差)。而这两种情况在坐标系上体现出来的形式都是两条斜率为 \(1\) 的直线的半平面,也就是说,我们要保证在从起始点走到终止状态的过程中始终在这两条线内部的区域。同时注意到如果能走到终止状态,两条线是不可能都被碰到的。所以用总方案数减去碰到上面那条线的方案数再减去碰到下面那条线的方案数就好了,这是三个组合数相减。

现在考虑所有的终止状态,它们的横纵坐标之和都相等,如果起点确定了对于每个终止状态的方案数都是三个组合数相减,其中组合数 \(\binom{a}{b}\)\(a\) 是确定的,因此可以预处理组合数前缀和,单次询问可以 \(O(1)\) 计算答案。

再考虑初始时有些位置是给定的,假设给定了 \(p_x=y\),那么前 \(y\) 个数填完后在环上形成的一段区间一定有一个端点是 \(x\),换而言之此时只有两个可能的区间。假设所有给定的数从小到大依次为 \(p_{x_1}=y_1,\cdots,p_{x_k}=y_k\),那么我们要先从 \((0,0)\) 到达 \(x+y=y_1-1\) 上的两个点,再从 \(x+y=y_1-1\) 上的两个点到达 \(x+y=y_2-1\) 上的两个点,……,最后从 \(x+y=y_k-1\) 上的两个点到达 \(x+y=n-1\) 上且在两条限制的线内部的所有点的方案数。实际上无论起点在哪里,只要 \(y_1\) 一出现,此时可能的区间就只有两个,那么只需要分别求出所有起点到这两个区间的方案数,在分别计算这两个区间经过上述历程到达最终的点的方案数。可以发现这就是 \(O(n)\) 个和没有给定 \(p\) 时的问题一样的子问题,每个子问题可以 \(O(1)\) 计算。

时间复杂度 \(O(n)\),空间复杂度 \(O(n)\)

12.QOJ#21657. 【PR #5】和平共处

把蚂蚁看成点,每个白点向左下的所有黑点连一条边,问题等价于求最大匹配,这又等于总点数减最大独立集。考虑最大独立集中的所有黑点,它们的右上的白点都不能在最大独立集中,也就是右上的所有黑点都在最大独立集中;白点同理。那我们可以根据所有黑点右上区域的并的边界,把所有点分成边界(含)右上方的点集 \(A\) 和边界(不含)左下方的点集 \(B\),那么最大独立集就是 \(A\) 中黑点数加 \(B\) 中白点数。

可以发现随着白点的加入最优边界只会向右上移动,否则可用反证法说明之前的方案不够优。考虑分治,现在要求 \([l,r]\) 时刻的答案,先求出 \(mid\) 时刻的边界,在 \(mid\) 时刻前 \(A\) 中的点集一定在边界右上方,在 \(mid\) 时刻后 \(B\) 中的点集一定在边界左下方,这两部分答案可以直接算,所以每个点都只要递归进一边做,总共会被递归 \(O(\log n)\) 次,所有点被涉及到的总次数为 \(O(n\log n)\)。考虑一个有 \(c\) 个点的问题怎么快速求解边界,要求最大独立集,我们再把它转成最大匹配,这可以直接贪心:把所有点按 \(x\) 坐标排序,维护一个集合表示待匹配的白点,每次碰到一个白点就加到集合里,碰到一个黑点就在集合里找 \(y\) 坐标不超过它且最大的白点相匹配,这样可以求出最大匹配。再用 Konig 定理构造出最大独立集(可以用线段树和 set 或二维线段树维护),独立集中的所有黑点和白点都知道了,边界自然也就知道了,时间复杂度是 \(O(c\log c)\) 的。

总时间复杂度 \(O(n\log^2 n)\),空间复杂度 \(O(n\log n)\)

13.QOJ#4273. Good Game

每次选择长为 \(2\)\(3\) 的相同字符连续段删去,等价于每次选择长度大等于 \(2\) 的相同字符连续段删去,并且可以发现如果一次删的不是极长连续段一定不优。那么对于原串的每个极长连续段,如果其长度至少为 \(2\) 那就用 \(2\) 表示,否则用 \(1\) 表示,这样问题就转化为了每次可以删掉一个 \(2\),如果其两边都有数字那就可以合并成一个 \(2\),问是否能删空。

首先考虑新串长度为 \(2k+1\) 的情况,如果最中间的元素是 \(2\) 则一定能删空;否则,最中间的元素是 \(1\),考虑最中间的 \(1\) 在新串中的极长连续段的长度,如果至少为 \(k\),那就没法删空,可以用归纳法证明;否则,找到该极长连续段左右两侧的第一个 \(2\),并将序列划分成左边的 \(2\) 左侧、左边的 \(2\) 和右边的 \(2\) 之间、右边的 \(2\) 右侧三段区间,设三段区间分别有 \(a,b,c\) 个元素,满足 \(a+b+c=2k-1\)\(b\le k-1\)\(a+b+1\ge k+1\)\(b+c+1\ge k+1\),那么选择 \(k-c\) 次左边的 \(2\) 后三段区间分别剩 \(a+c-k,b+c-k,c\)\(1\),可以发现三段区间的 \(1\) 的个数都非负且此时右边的 \(2\) 已经到最中间了,于是也能删空。

对于新串长度为 \(2k\) 的情况,若能被删空一定会有一个 \(2\) 被删去时其两边只有一边有数,找到最早的满足条件的 \(2\),可以发现其是由靠边上的连续的一段 \(1,2\) 合并成的,也就是说必要条件是存在一个分界点使得两边串长都是奇数、且单独看这两个串都是合法的。而由串长为奇数时的构造方案可知除了最后一步外不会删最旁边的数,故这也是充分条件。所以枚举分界点使两边长度都为奇数,判断两边是否都可行即可。

时间复杂度 \(O(n)\),空间复杂度 \(O(n)\)

posted @ 2023-01-19 12:01  18Michael  阅读(10)  评论(0编辑  收藏  举报