模拟赛随机记录

记录模拟赛的好题~

10.31-T3 move

感受到了其实维护直径的功能还是很强大的。

两棵树,于是考虑在一棵树上 dfs,维护另一棵树上的信息。具体地,考虑在第二棵树上的每个点下面挂一个点,边权为 dis1(A,u)dis1(A,u)。考虑每次 dfs 中从 uvu\to v,其实就是一段区间的 dis1(A,u)dis1(A,u) 加上边权 ww,剩下的减去 ww

再来考虑距离和最大这个要求,考虑现在变成了在第二棵树上找离 BB 最远的点的距离,这显然可以通过维护直径做。也就是说,现在要维护的就是区间加,全局直径,直接做就行。

其实感觉是简单题啊,自己绕晕了

11.7-T3 sales

一个暴力做法显然是枚举去到的最远的位置,记选 ii 个数时的这个位置为 fif_i,则显然有结论:fif_i 单调不降。于是考虑类似决策单调性的分治做法,每次算 midmid 的答案,然后分治。用主席树或精细实现的线段树维护做到 O(nlog2n)O(n\log^2n)

11.8-T2 bit \color{blue}\Diamond

感觉是一个很新颖的角度:\color{blue}\Diamond 从 popcount 的角度考虑按位与/或。有 popc(xSx)maxxS(popc(x))\operatorname{popc}(\bigvee_{x\in S}x)\ge\max_{x\in S}(\operatorname{popc}(x))\bigwedge 同理。于是考虑枚举最后的 popc=k\operatorname{popc}=k,则所有 popc<k\operatorname{popc}<k 的一定放在按位或中,popc>k\operatorname{popc}>k 的一定在与中。

popc=k\operatorname{popc}=k 的数一定只有一种。证明考虑如果多余一种,若有多于一种放同一集合显然不行,若放不同集合中,由于 popc=k\operatorname{popc}=k,则对应值一定等于该数,不相等。

于是只需要看这种数有多少个,讨论是全放一个集合,还是两个集合都放即可。剩下的用 st 表简单维护即可做到 O(nlognlogV)O(logV)O(n\log n\log V)-O(\log V)

11.11-T3 spr \color{blue}\Diamond

怎么有人能对着第一步 dp of dp 看那么久的?

首先如果没有 1-1 就是简单 dp:设 fi,0/1/2f_{i,0/1/2} 表示考虑前 ii 位,第 ii 位出了 0/1/20/1/2 的最大分数。那么有个显然的 dp of dp:设 dpi,x,y,zdp_{i,x,y,z} 表示当前考虑到第 ii 位,fi,0/1/2f_{i,0/1/2} 分别为 x,y,zx,y,z 时的方案数。转移显然。这是 O(n4)O(n^4) 的。

然后考虑优化状态。显然每一位都有一种是不能出的,所以实际上只用记录两种。设 dpi,x,y,0/1/2dp_{i,x,y,0/1/2} 表示 0/1/20/1/2 不能出,剩下两个 dp 值依次是 x,yx,y 的方案数。O(n3)O(n^3)

这里看似无法优化了。\color{blue}\Diamond 但是事实上对于这种记录两个数的 dp,有一个可能的优化是,由于我们并不关心两个的具体值,这题中其实最后统计答案时也只关心 max(x,y)\max(x,y),可以考虑记录两个值的差,对于对于其他的信息可以提前处理或忽略。

对于这题,考虑令 x=nx=n,记录 yxy-x,再在转移过程中处理 xx 和真实值之间的差带来的贡献。则设 dpi,j,0/1/2dp_{i,j,0/1/2} 表示 yx=jy-x=j,不能选的是 0/1/20/1/2 的方案,转移时处理 ansans 即可。

11.13-T2 seq

首先有个显然的 O(n2)O(n^2) dp:设 dpi,j,0/1dp_{i,j,0/1} 表示当前考虑 ss 的前 ii 位,tt 匹配到第 jj 位,sis_i 是否和 tjt_j 匹配是否可行。转移是 dpi1,j,1dpi,j,0,dpi1,j,0dpi,j,0(si1=si),dpi1,j1,0/1dpi,j,1(si=tj)dp_{i-1,j,1}\to dp_{i,j,0},dp_{i-1,j,0}\to dp_{i,j,0}(s_{i-1}=s_i),dp_{i-1,j-1,0/1}\to dp_{i,j,1}(s_i=t_j)

由于是可行性 dp,且 n=105n=10^5,不难想到 bitset。转移不难表示。

但是有个问题:由于要构造,空间会爆炸。所以加上两个优化:首先构造时可以考虑,每次判断 dpi1,,1dp_{i-1,*,1} 是否可行,可行就直接去到 11 否则 00,这样只用记录 dp,,1dp_{*,*,1},另一维滚动。其次发现一定有 jij\le i,于是考虑前 5×1045\times 10^4 位用 5×1045\times 10^4 的 bitset 存,后面用 10510^5 的,中间衔接的时候枚举每个为 11 的位置即可。于是 O(n2ω)O(\frac{n^2}\omega) 解决。

11.15-T2 show

显然要 dp,设 dpidp_i 表示考虑 [1,i][1,i] 的方案数。考虑如何转移。

首先,可以根据上一次出现的相同的数的位置确定 >1>1 的是在奇数位还是偶数位,不妨钦定在偶数位。那么限制就分成了两部分:奇数位的数两两不同,偶数位的至少出现两次。

先考虑第一个限制,显然可以找到第一个出现相同的数的位置解决。第二个限制考虑每次加入一个 aia_i 时,给 aia_i 上一次出现的位置 jjii 打上标记,表示这些位置不能作为左端点,并且去除之前的标记。于是每次就只能从没有标记的位置转移。结合上面的,就是要求一个区间的最小值和最小值对应位置的 dp 值的和,线段树处理即可。

11.18-T4 douglas

最重要的就是如何避免算重。考虑这样一个策略:尽可能靠 yy 小的位置走,如果这种路线一定要往上再往上走。这样一定会不重不漏地算上每种走法。

再考虑如何计数,不难发现这样一定是一直往右走,直到某个位置往上再往右一步走到 (x1,y2+1)(x_1,y_2+1)。于是扫描线,维护区间求和,区间推平,单点赋值。同时对于障碍堵住的位置,再开个线段树/set 维护一下哪些位置不能经过再处理即可。

11.19-T4 d

首先将问题转化为:将 [2,2n][2,2^n] 内的数分成 nn 个大小分别为 20,21,22,,2n12^0,2^1,2^2,\cdots,2^{n-1} 的集合,使得每个集合中的最小数都不在 SS 中。但是发现都不在 SS 中这个条件比较难看,考虑容斥变成钦定若干个集合的最小值在 SS 中,其他任意。为什么这样会比较好做?因为限制了 S100|S|\le 100 使得我们可以考虑从这里入手。

于是进行一个 dp。考虑从小到大判断每个 SS 中的数是否为某个集合的最小值,如果是就选一个集合放,否则任意填进已经选了的集合里面的一个空位。对于不在 SS 内的数则也是找空位填。但是每个集合大小不同,不过只有 nn 个集合,于是考虑直接状压。设 dpS,idp_{S,i} 表示当前已经钦定了最小值的集合为 SS,选到第 ii 个在 SS 集合中的数的方案数。转移乘上组合数即可。O(2nSn)O(2^n|S|n) 解决。

11.21-T4 graph \color{blue}\Diamond

一种很新的线段树分治。

首先考虑判定。不难发现有解当且仅当每个连通块大小都为偶数,证明是简单的。同时显然答案单调不升。于是考虑从后往前做,每次不断加权值最小的边直到满足条件。

但是发现一个问题:加边之后,由于每条边存在的时间是一个后缀,所以还要删边。怎么办?\color{blue}\Diamond 考虑线段树分治,但是当处理 tt 的时刻的答案时,考虑找到这条边的出现时间 ll,于是这条边事实上会对 [l,t][l,t] 内的询问有贡献,再拆成 [l,t1][l,t-1][t,t][t,t],于是在加入这条边时再在 [l,t1][l,t-1] upd 这条边即可。

11.22-T4 calc \color{blue}\Diamond

\color{blue}\Diamond 对于这种计算每个点对之间的贡献的题,可以考虑分治。

首先对于 rlr-l 比较小的(10\le 10)的可以直接暴力。然后考虑当前分治中心为 midmid,计算 i[l,mid],j[mid+1,r]i\in[l,mid],j\in[mid+1,r]d(i,j)d(i,j) 的贡献。

容易发现,(i,j)(i,j) 之间路径一定经过 mid+1,mid+2,mid+3mid+1,mid+2,mid+3 之中至少一个点,因为一次最多跳 33 的距离。于是处理出 fi,j=d(i,mid+j)f_{i,j}=d(i,mid+j),则要求的就变成了 limidmid+1jrmink3fi,k+fj,k\sum_{l\le i\le mid}\sum_{mid+1\le j\le r}\min_{k\le 3}f_{i,k}+f_{j,k}

\color{blue}\Diamond 对于这种计数若干个 min\min 的和的问题,考虑钦定一个为 min\min,然后计算它真正为 min\min 时的贡献。不妨钦定 fi,1+fj,1f_{i,1}+f_{j,1}min\min,则条件为 {fi,1+fj,1fi,2+fj,2fi,1+fj,1fi,3+fj,3\begin{cases}f_{i,1}+f_{j,1}\le f_{i,2}+f_{j,2}\\f_{i,1}+f_{j,1}\le f_{i,3}+f_{j,3}\end{cases}。移项,把和 ii 有关的以及和 jj 有关的分开,{fi,1fi,2fj,2fj,1fi,1fi,3fj,3fj,1\begin{cases}f_{i,1}-f_{i,2}\le f_{j,2}-f_{j,1}\\f_{i,1}-f_{i,3}\le f_{j,3}-f_{j,1}\end{cases}。不难发现这是一个二维偏序的形式,离线下来排序,然后扫描线,用 BIT 维护解决。时间复杂度 O(nlog2n)O(n\log^2n)

11.23(PNR round 8)-T3

首先考虑给定柱子高度如何算总积水。考虑柱子 ii 的积水高度,设 fi=maxjihj,gi=maxjihjf_i=\max_{j\le i}h_j,g_i=\max_{j\ge i}h_j,则高度为 min(fi,gi)hi\min(f_i,g_i)-h_i,即总积水为 min(fi,gi)hi\sum\min(f_i,g_i)-h_i

因为 min(fi,gi)\min(f_i,g_i) 既和前面的有关又和后面的有关,于是考虑如何去掉这个 min\min。不难发现 min(fi,gi)\min(f_i,g_i)fif_iii 是一段前缀,取 gig_i 的是剩下的后缀。若令 figif_i\le g_i 时取 fif_i,则这个分界点,即最后一个取 fif_i 的位置是最后一个全局最大值的位置。

于是枚举操作完后最后一个全局最大值的位置 pp,则可以分开算 ipfihi\sum_{i\le p}f_i-h_ii>pgihi\sum_{i>p}g_i-h_i。对于前面的,考虑设 dpi,j,kdp_{i,j,k} 表示当前枚举到 ii,已经选了 jj 个变为 00,当前的最大值位置在 kk 的方案数。转移枚举这一位选不选,再看最大值是否变化即可。后者也是类似的。统计答案的时候枚举左右两边各选了多少个,以及右边的最大值即可。时间复杂度 O(n2k)O(n^2k)

考虑优化,不难发现由于最多删 kk 个数,所以不同的前/后缀最大值最多只有 k+1k+1 个。预处理出这 k+1k+1 个前/后缀最大值,合并答案时也是一样,不同的全局最大值只有 O(k)O(k) 个。依据实现做到 O(nk2)O(nk^2)O(nk3)O(nk^3)

后面都是省选模拟赛。

12.3-T1 count \color{blue}\Diamond

下令 nnk,Bnn\leftarrow nk,B\leftarrow n

首先有个暴力做法:每次直接枚举 i,ji,j 算。复杂度为 O(nB)O(nB)

\color{blue}\Diamond 由于数据范围限制了 nn 的大小,所以考虑找出另一种做法,类根号分治。

\color{blue}\Diamond 同时对于这种算某个东西的 kk 次方,可以考虑拆开算每一项的贡献(ARC124E)。对于这题,拆成 (aj2j)3(\sum a_j2^j)^3 的贡献。考虑枚举三位 i,j,ki,j,k,产生贡献当且仅当这三位异或起来都是 11,处理出 cxc_x 表示 i,j,ki,j,k 三位的值拼在一起为 xxaa 的个数,则贡献的对数为 i<4ci×ci7\sum_{i<4}c_i\times c_{i\oplus 7}。这样复杂度为 O(n3B2)O(\frac{n^3}{B^2})

结合在一起,容易发现当阈值取 B=n23B=n^{\frac23} 时复杂度取得最小值 O(n53)O(n^{\frac53})。但是还是无法通过。

\color{blue}\Diamond 但是由于是一堆异或运算,容易想到 bitset 优化。对于做法 11,考虑类似 bitset 地 ω\omega 位一块,每块算异或和,复杂度 O(nBω)O(\frac{nB}\omega)。对于做法 22,考虑预处理出 ai,j=0/1a_{i,j}=0/1ii 的 bitset,于是可以 O(nω)O(\frac n\omega) 得到一个 cic_i 的值。复杂度变为 O(n32kB2ω)O(\frac{n^32^k}{B^2\omega})。取 B=n232k3B=n^{\frac23}2^{\frac k3},复杂度为 O(n532k3ω)O(\frac{n^{\frac 53}2^{\frac k3}}{\omega}) 可以通过。

12.4-T1 graph \color{blue}\Diamond

对了 3h 脑电波。

首先找出一棵生成树并进行编号。如果一直从“确定某个点的编号”的方向考虑是非常没有前途的。仔细思考,如果每次到一个编号未知的点再返回就不用确定编号了。问题就变成了能从这里获取什么信息。

\color{blue}\Diamond 灵光一闪想到拆位。具体地,进行 log3n\log_3n 轮,每轮将 uu 点染成 (n)3(n)_3 的一位,对于每条非树边,在祖先的位置询问后代的编号的三进制这一位的值,则最后就能拼成真实值。精细实现刚好 14m14m。1

12.4-T2 kte

由于上述原因,赛时会了没打出来。

首先设 fif_i 为当前前 ii 小的和,gig_i 为前 ii 大的和。则答案显然为所有 [fi,gi][f_i,g_i] 的并集。但是这个完全不能维护。此时发现比较烦的是有区间之间有交的情况,于是想怎么处理这种情况。

这里就有一个非常厉害的性质:注意到在 in2i\le\frac n2 时,若 gifi1g_i\ge f_{i-1},则对于 gi+1=gi+x,fi=fi1+yg_{i+1}=g_i+x,f_i=f_{i-1}+y,由于 x>yx>y,所以一定有 gi+1fig_{i+1}\ge f_i!对于 i>n2i>\frac n2 的情况也是类似的。于是可以二分出这两个边界,中间的就是 maxgiminfi\max g_i-\min f_i,剩下的就是 gifi+1\sum g_i-f_i+1。线段树维护即可。

12.5-T1 game

考虑嗯推 SG。太有趣了!

首先不妨考虑一条链的情况。设 du=maxvsubtree(u)depvd_u=\max_{v\in\operatorname{subtree}(u)} dep_v,则不难发现整条链可以视为一个二进制数,sgu=csubtree(u),cv=12dudepusg_u=\sum_{c\in\operatorname{subtree}(u),c_v=1}2^{d_u-dep_u}

考虑拓展成树。首先如果操作了根,则剩下的是个若干个子问题,则 sgu=vsonusgvsg_u=\bigoplus_{v\in son_u}sg_v。又由于操作完后 maxsgv=2dudepu1\max sg_v=2^{d_u-dep_u}-1,则 sgu2dudepusg_u\ge 2_{d_u-dep_u}

还能不能更大?剩下的情况一定是不操作根节点的,于是一定有 sgsgusg\ge sg_u。此时直接忽略根节点,则 sg=sgvsg=\bigoplus sg_v。然而所有后继状态都能到达 sg<2dudepusg<2^{d_u-dep_u}sgsg 值,于是就有 sgu=sgv2dudepusg_u=\bigoplus sg_v\oplus 2^{d_u-dep_u}。dp 上去就行了。

好麻烦

12.5-T2 seq \color{blue}\Diamond

首先不管 P,NP,|N|,用一个二元组 (xi,yi)(x_i,y_i) 分别表示当前 ai0a_i\ge 0ai<0a_i<0aia_i 之和。则不难发现最后要求的形如 maxax+by\max ax+by。不难发现这需要维护一个下凸包。

于是现在需要维护的就是:区间 xi,yix_i,y_ikk,在凸包上二分。\color{blue}\Diamond 注意到对一个点集里的所有点的 xi,yix_i,y_i 整体加不会影响凸包,于是考虑序列分块/操作分块。当时写了操作分块,具体就是每 m\sqrt m 个操作一块,则能保证 m\sqrt m 块内,每块的凸包形状都不变。于是询问就在这些凸包上面二分即可。

序列分块似乎更好写,总之复杂度都是 O(mmlogm)O(m\sqrt{m\log m})

12.6-T1 i \color{blue}\Diamond

从点分树的角度考虑。考虑如果已经知道了两棵树分别的点分树形态,如何合并这两棵点分树。

这里场上犯了一个错误,就是过于在意原本的树对应合并后的树的实际形态,于是方向一直是把原来的树就拆成若干个连通块记录。\color{blue}\Diamond 事实上可以直接把原来的树记录,再考虑树的合并。

考虑 uu 子树的点分树的根 rturt_u 以及 vvrtvrt_v。如果在不影响原本两棵点分树的相对形态的基础上合并的话,那么首先新树的根一定是 rturt_urtvrt_v,不妨令其为 rturt_u。然后此时除了 uu 所在子树都已经是确定了,于是考虑 uu 子树方向的下一个点,则一定是原树这个方向的下一个点或 rtvrt_v。以此类推,发现本质上只需要将 rtuu,rtvvrt_u\to u,rt_v\to v 的两条链合并。于是设 dpu,idp_{u,i} 表示 uu 子树形成的点分树中,depu=idep_u=i 的方案数,每次网上合并即可。

12.6-T2 ii \color{blue}\Diamond

套路扫描线,然后发现要维护的就是两种操作:区间和 kkmin\min,区间查询 l\ge l 的个数。由于 l\ge l 的一定在查询区间中,所以实际上是全局查。

考虑第一种操作,肯定需要 Segment Tree Beats 维护。于是考虑怎么维护后者个数。\color{blue}\Diamond 考虑一个很本质的东西:Beats 实际上就是将一次区间取 min\min 操作变成 O(logn)O(\log n) 次区间将某个数全部变成另一个数的操作。于是再开一个 BIT 维护每种数有多少个,每次就是单点加减,最后直接查询即可。

12.8-T1 venture

std 做法好像非常简单,就是类似处理哈希冲突那样找到第一个没有填的点填上……

考虑如果一共要进行 xx 次攻击,则意味着 [1,x][1,x] 内的每一次攻击都要触发。于是答案就是 maxixii1aj\max_{i\le x}i-\sum\left\lfloor\frac{i-1}{a_j}\right\rfloor。于是有一个 O(nlognlnn)O(n\log n\ln n) 做法就是每次加入的时候,如果会产生影响就枚举 O(na)O(\frac na) 修改。上界是每个 aa 被枚举两次。

然后考虑单 log\log。考虑记 fi=ii1ajf_i=i-\sum\left\lfloor\frac{i-1}{a_j}\right\rfloor,则 fif_i 的前缀 max\max 一定是 [1,][1,*] 连续的一段。考虑直接维护前缀最大值的位置,则每次就形如找若干个位置删掉,查询某个前缀的没有删掉的数量。由于只会删 O(n)O(n) 次,于是精细实现就是 O(nlogn)O(n\log n) 的了。

12.9-T1 tree

容斥!容斥!

首先又是那个 trick:看到 xkx^k,拆成若干项的贡献。那么问题就变成了若干个颜色一定出现的方案数。注意到我们并不关心具体是哪些颜色,于是算一次,最后乘上组合数。

然后考虑若干个颜色一定出现,典型的容斥,变成钦定若干个颜色不出现的方案数。然后考虑数这个东西。如果没有限制的话,考虑先定一个点,剩下就全是 m1m-1。但是发现这个做法可拓展性不强。

此时注意到我们要求“所有相邻的点的颜色都不相同”,这也是一个容斥的性质。考虑钦定若干条边对应点一定相同,于是分成若干个连通块分别算。而这样每个连通块的方案数就只和其中是否包含关键点有关,非常简洁。于是设 dpu,0/1dp_{u,0/1} 表示当前 uu 所在连通块是否有关键点,合并子树时考虑相连的边选不选,同时转移方案数和容斥系数。最后再根据这个求答案即可。

12.9-T2 cut

考虑如果只能选一条树边,那么令分开的子树为 uu,则 uu 子树内的非树边一定全都要删去。那么如果还有另一个分开的子树 vv,容易发现此时 uu 子树连向 vv 子树的边就不用删了。于是设 fif_i 表示 ii 子树内非树边的数量,gi,jg_{i,j} 表示 ii 子树连向 jj 子树的数量。则 ansi=minjfi+fj2gi,jans_i=\min_jf_i+f_j-2g_{i,j}

由于数据范围小且 3s 时限,于是直接静态链分治,对于每一棵子树分别算,那要维护的就是链加全局最小值。O((n+m)log3n)O((n+m)\log^3n) 冲即可。

12.11-T1 kristoff

很 ARC 风格的题,不过放 ARC 最多 2700?

首先考虑找出所有极长的可操作区间。容易发现这些区间一定是不交的。然后还有个性质:每次操作一定会操作一个极长的可操作区间,否则一定不优。证明是简单的。

然后就只用考虑每个极长区间的第一个和最后一个字符 ai,bia_i,b_i。更进一步,由于 bi=ai+1b_i=a_{i+1},于是只用考虑 aia_i。再考虑现在每个操作的影响,容易发现,一次操作就是选择 ai=ai+1a_i\not=a_{i+1} 然后删掉 ai,ai+1a_i,a_{i+1}。这是经典问题,只需要每次找剩下数量最多的字符删即可。

12.11-T3 zdd

转换题意,每次修改相当于给这条边一个 tt 的标记,询问就是问从 uu 开始,走单调上升的标记能到达的点的数量。显然能到达的点形如一个连通块。

既然是连通块,想到点分治。对于一个分治重心 rtrt,考虑求出每个点 uu 最早到 rtrt 的时间 fuf_u 以及每个标记 ii 最晚什么时刻从根出发能到这个标记 gig_i。则若询问 (u,t)(u,t) 能到达 vv,则存在一个在 vv 的父边上的标记 ii,满足 fu<gi,i>tf_u<g_i,i>t。扫描线维护即可。

12.13-T3 greatcar

观察题面,发现限制形如若干个区间,每个区间内的车数量大于/小于等于某个数。考虑转成前缀和 ff,并且把车变成一个点。同时注意到实际上有用的位置不是很多,离散化,于是限制就变成了:

  • fifi+1f_i\le f_{i+1}

  • fifj+ijkf_i\le f_j+\left\lceil\frac{i-j}{k}\right\rceil

  • fifj+[apjbpki],(j<i)f_i\ge f_j+\sum[a_p\ge j\wedge b_p-k\le i],(j<i)

  • fyikfxi+cif_{y_i-k}\le f_{x_i}+c_i

于是显然可以差分约束。但是如果直接跑 spfaO(n3)O(n^3) 的。于是考虑用脑求负环。

不难发现负权边只有 fifj+[apjbpki],(j<i)f_i\ge f_j+\sum[a_p\ge j\wedge b_p-k\le i],(j<i)。同时,容易发现如果有负环,则一定存在一个负环只有一条负权边。证明考虑 iji\to j 的边权是被 [i,j][i,j] 完全包含的 [ai,bik][a_i,b_i-k] 区间的个数。于是如果走了 ij,jki\to j,j\to k 显然不如直接走 iki\to k。(不过实际上就算没有这个性质也能做?)

于是现在只需要求出 disi,jdis_{i,j} 表示只走非负权边,iji\to j 的最短距离。直接暴力跑还是 O(n3)O(n^3) 的。但是可以发现,这里的瓶颈在于 fifj+ijkf_i\le f_j+\left\lceil\frac{i-j}{k}\right\rceil 的边有 O(n2)O(n^2) 条。但是容易发现这是一个很好维护的形式,只需要拆开下取整,变成和 imodki\bmod k 有关的问题就能用 SGT 维护转移。时间复杂度 O(n2logn)O(n^2\log n)

1.19 T2-B

首先最少删的数量显然为 n2×m2\left\lfloor\frac n2\right\rfloor\times\left\lfloor\frac m2\right\rfloor

考虑 n,mn,m 皆为奇数的情况。容易发现每个 x,yx,y 皆为偶数的 (x,y)(x,y) 都一定要删。答案为 11

再考虑有一个奇数的。不妨令其为 nn。于是发现 nn 这边的横(?)坐标就已经是确定的。而 mm 这边,每一行都有可能有一段前缀,删除的位置 yy 为偶数,剩下的后缀为奇数。于是方案数即为 (m2+1)n12(\frac m2+1)^{\frac{n-1}2}

剩下 n,mn,m 皆为奇数的情况是否是把另一维的贡献也乘上就行?手玩样例可以发现有一种情况不合法:

.#..
...#
#...
..#.

这种情况中每一行/列对应的都是合法的,但是中间空出来了一个 2×22\times 2 的块。同理,对这个情况水平对称一下也不合法。

于是考虑 dp。注意到 n25n\le 25,也就是 n212\frac n2\le 12。于是考虑状压记录一个状态。设 dpi,S,jdp_{i,S,j} 表示当前考虑到第 2i1,2i2i-1,2i 列删除的位置,其中每一个删除位置的列坐标的奇偶性为 SS,并且前 jj 个的行坐标为偶数的方案数。从 dpi1,S,jdp_{i-1,S,j} 转移到 dpi,,kdp_{i,*,k} 时,SS 中有些为 00 的位置一定要变成 11。其他 00 任意。于是把强制变成 11 的位置统计上,然后高维前缀和即可。

时间复杂度 O(m2n2n2)O(m2^{\frac n2}n^2),但是由于带很多 12\frac 12 的常数所以可过。

1.19 T3-C

考虑二分答案。建出 kruskal 重构树。u,vu,v 都尽可能往上跳,即找到能到达的最大连通块。然后只用判断是否有连接这两棵子树的边。直接线段树合并预处理出每个子树能到的点的 dfndfn,查询的时候只用在线段树上查询一段区间的和是否 >0>0 即可。O(qlogmlogV)O(q\log m\log V)

2.6 T3-conquer

比较套路的 dp of dp 题,但是赛时心态爆炸所以没开。

首先计数指定 lcs 的序列,听起来就很像 dp of dp。求 lcs 的 dp 是简单的,即 fi,j=max(fi1,j,fi,j1,fi1,j1+[si=tj])f_{i,j}=\max(f_{i-1,j},f_{i,j-1},f_{i-1,j-1}+[s_i=t_j])。考虑状态怎么设。考虑当前处理到 TT 的第 ii 位,首先要存下一些原 dp 的状态,但是把所有 dpj,idp_{j,i} 都存下来是不可能的。

此时发现由于要求 lcs>nklcs>n-k,所以如果 TT 的第 ii 位匹配到了 j<ikj<i-kj>i+kj>i+k 显然都是不可能的了。此时状态数为 O(n2k+2)O(n^{2k+2})

同时还能发现,显然有 0fj,ifj1,i10\le f_{j,i}-f_{j-1,i}\le 1,所以只需要记录 fik,if_{i-k,i} 的值,剩下每一位状压,就是 O(n22k)O(n^22^k) 的。

再再再观察,发现一定有 fik,i[i2k,ik]f_{i-k,i}\in[i-2k,i-k],否则 fi,i<ikf_{i,i}<i-k,显然无法找到长为 nkn-k 的 lcs。于是状态数只有 O(nk22k)O(nk2^{2k}) 了。可以接受。

再考虑转移。如果暴力枚举当前位置字符就是 O(nΣk222k)O(n|\Sigma|k^22^{2k}) 的,不太行。但是再再再再发现,对于一个位置 ii,如果和某个位置 jj 匹配在最后的 lcs 中,那么 ijk|i-j|\le k,于是这个位置能填的本质不同的字符只有 O(k)O(k) 种。O(nk322k)O(nk^32^{2k}) 可以通过,但是题解说可以 O(nk222k)O(nk^22^{2k}) 不是很懂,看了 std 似乎是他写错了。。。

2.6 T2-cover \color{blue}\Diamond

不管怎么样,我觉得需要利用到模数性质写一句“由于答案可能很大……”是非常不负责任的表现。。。总之尽量讲讲吧?

由于模数为 22,于是很可能就是构造双射去掉很多情况然后做,并且可以用 =n最小点覆盖=n-最大独立集 转化。场上到这里就不会了。

\color{blue}\Diamond 事实上一个可能的思路是关注一个极小部分,并通过构建双射去掉一部分状态。考虑直接拎出来两个点,比如 1,21,2。考虑除了 (1,2)(1,2) 之外边,此时 1,21,2 的邻域如果不同,那么此时交换 1,21,2 的邻域显然图是同构的,于是最大独立集相同,直接抵消掉。否则?不难发现 1,21,2 完全相同,不妨直接合并成一个点往下做。

以此类推,我们每次可以对两个在原图中对应的点数相同的点进行如上操作。最后一定会形成若干个对应原图 2ki2^{k_i} 个点的大点。此时再算最大独立集,就可以贪心地枚举 kik_i 最大的点,能选直接选。并且这个状态显然可以压进一个 n\le n 的二进制数 KK

但是我们还没算方案数!不过此时可以通过贪心的方式选点,于是。很难注意到另一个非常厉害的性质:如果存在一个没有选的点 ii 和一个 kj<kik_j<k_ijj,那么 i,ji,j 间是否有连边不影响。证明考虑,判断 ii 是否取的时候不关心 jj 的状态,判断 jj 是否取时,由于 ii 一定不取,所以这条边存在与否也是没有影响的。于是此时又形成了双射。

所以我们只需要关注全部点都取或者只有 kik_i 最小的点没有取的情况。固定序列 kmk_m 时,考虑算分别的方案数。前者显然为 11,后者考虑只有 kik_i 最小的点和其它点的可能连边,但是不能全不连,于是为 2m112^{m-1}-1,都为奇数。对应地,图的最大独立集就分别是 K,Klowbit(K)K,K-\operatorname{lowbit}(K)

那问题只剩下如何求出状态为 KK 的点集的方案数。设 dpi,Sdp_{i,S} 表示原图有 ii 个点,上述状态为 SS 的方案数。考虑加入一个点,要不就是加进去不断合并,dpi1,S1dpi,Sdp_{i-1,S-1}\to dp_{i,S}。要么就是合并到一半被删掉了,那么此前 SS 后面的 00 全都是 11dpi1,S+lowbit(S)1dpi,Sdp_{i-1,S+\operatorname{lowbit}(S)-1}\to dp_{i,S}。然后再处理答案。O(n2)O(n^2) 预处理即可。

2.8-T3 luck

一句话:每次询问枚举短的路线,在长的上二分,再记忆化可过。

考虑分析复杂度。记 k=Kik=\sum K_i。询问 x,yx,y,令 Kx<KyK_x<K_y。若 KxkK_x\le\sqrt k,显然每次不会枚举超过 O(k)O(\sqrt k) 个位置。这部分是 O(qklogk)O(q\sqrt k\log k) 的。

否则,考虑每个位置被枚举了几次。因为 Ky>kK_y>\sqrt k 所以不同的 yy 最多有 k\sqrt k 个。记忆化之后,每个位置就会被枚举到不超过 k\sqrt k 次。所以这部分是 O(kklogk)O(k\sqrt k\log k) 的。

2.9-T2 game \color{blue}\Diamond

首先考虑 S=2S=2 怎么做。发现每一行只有两个数,这就让人很想连边。连完边就想在这个图上走路。那首先容易发现,如果可以走出一条回路,每条边按照走的方向确定这行的元素顺序,那么对于回路中出现的所有元素,这部分在两列中出现的次数都是一样的。那么如果原图有一条欧拉回路那就显然结束了。

但是很多时候没有。但是发现对于奇度数的点,在某一列多放一个没有什么影响。而如果走出一条路径,只有两端的元素在两列中的数量不是一样的。于是只需要每次消掉两个奇度数点,剩下的再对每个连通块跑欧拉回路即可。实现上,直接枚举每个奇度数点,随便 dfs 一条路径直到走不了就能消掉两个奇度数点。剩下随便 dfs 就行。

和 yhd 交流的时候知道了上面那个东西也可以用之前忘了哪次讲题的,\color{blue}\Diamond 建一个虚点连所有奇度数点的 trick 做。没想到。

然后考虑 S>2S>2。发现我们这个构造方法是非常强的,一定有解。然后发现一个性质:将 xx 尽可能平均分成 2k2^k 份,可以通过重复 kk 次:对当前每一份都尽可能平均分成 22 份 的过程完成。于是每次把前一半的视作 S=2S=2 时第一列的,剩下的视作第二列的,做 S=2S=2,再递归求解即可。

2.9-T1 swap \color{blue}\Diamond

题解第一步讲的非常好!直接放了。

考虑我们是要求 f(S,l,r),Tf(S,l,r),T 相同的位置数,其中 f(S,l,r)f(S,l,r) 表示 SS 经过 [l,r][l,r] 内的操作后的结果。这个东西不好求,\color{blue}\Diamond 发现一个原因是 l,rl,r 两个未知数都在左边,于是考虑移到右边来。考虑两边同时进行 [r+1,n][r+1,n] 的操作,显然要求的答案不变,但是这样就变成了 f(S,l,n),f(T,r+1,n)f(S,l,n),f(T,r+1,n) 相同的位置数。显然都是可以预处理的。

然后考虑求答案。顺便参杂一点赛时的想法:\color{blue}\Diamond 注意到,如果我们枚举一个端点再考虑这个端点的最大答案,我们并不知道答案这些位置是哪些,所以大概率还要枚举,不能接受。于是直接考虑枚举答案位置。

然后还有一个关键的结论,\color{blue}\Diamond 就是 popc(ST)=kpopc(S)popc(T)+2popc(S&T)\operatorname{popc}(S\oplus T)=k-\operatorname{popc}(S)-\operatorname{popc}(T)+2\operatorname{popc}(S\&T)。证明不难。于是 popc(S&T)popc(S\&T) 越大越好,枚举时也可以考虑直接枚举 S&TS\&T 算。

所以剩下的只需要对于一个 KK,求出最小的 ll,最大的 rr 使得 Kf(T,r+1,n),Kf(S,l,n)K\subseteq f(T,r+1,n),K\subseteq f(S,l,n)。处理出 f(S/T,,n)f(S/T,*,n) 后高维前缀最值即可。

2.10-T1 stone

首先题意即为在一个区间集合中选出若干个区间,最小化其交集,其次最小化区间的 maxrminl\max r-\min l。不难发现最优情况下一定只用选两个区间,并且第一问的答案为所有区间的交集。

若交集非空,则选出以交集左端点为 ll 的区间中的 minr\min r,右端点同理。否则,考虑对于每个位置,维护以其为 llfi=minrf_i=\min r 以及相对应的,gimaxlg_i\max l。于是要求的即为 mini<jfigj\min_{i<j}f_i-g_j。不难发现这可以在线段树 pushup 时合并地维护。

2.13-T2 education

快进到 link

给出题人好评,部分分相当有提示意义。

首先考虑 B18B\le 18。由于每个点只和与其绝对值 18\le 18 的点有关,于是从小到大枚举点,状压前 1818 个点的状态即可 O(n2B)O(n2^B)

然后考虑 BmodA=0B\bmod A=0。考虑对于 uv=A|u-v|=A 的一条链,上面 uv=B|u-v|=B 的边会分成若干条小链。对于 B>20B>20 的情况,这些小链长都 10\le 10,依次枚举每条小链,状压其状态,再处理大链上的边是否选即可。

再考虑 B>100B>100 的情况。不妨变成 2B>n2B>n 的情况。手玩一下小的图就会发现,可以通过某些排列这些点的方式,使得整张图变成一个类似网格图,但是有一条边从第一行连向最后一行的形状。再拓展一下,手玩一下 n=22,A=4,B=7n=22,A=4,B=7 的情况,发现此时变成了有三条这样的边。

然后思考一下是为什么,发现考虑这样一张图:每个点 uu 的右边是 u+Bu+B,下面是 u+Au+A,则这张图呈循环阶梯状二维彭罗斯阶梯。同时注意到每一行至多有 nB\left\lfloor\frac nB\right\rfloor 个点,则对应的竖着的边这是大概这个数量。然后结合上面的,只要断掉某一行的所有边,就变成了一个一般的阶梯状网格图。

然后考虑一个 dp:设 dpi,Sdp_{i,S} 表示当前处理到第 ii 行,该行从左到右每个点是否被选的状态为 SS 的方案数。考虑转移。行间转移考虑为 11 的对应位置一定为 00,否则存在对应的行间的边则对应位置可 0011。于是可以高维前缀和。行内的转移考虑类似高位前缀和或称 FMT 或称轮廓线 dp,依次枚举每条行内的边,枚举对应两个位置皆为 11 的状态转移到皆为 00 的状态。

这样做的复杂度,由于还要枚举断开的边的状态,所以是 O(n22nB)O(n2^\frac{2n}B) 的。根号分治,B20B\le 20 时跑上面的 O(n2B)O(n2^B),否则跑这个。可以通过。

其实看到部分分就猜到是根分了,而且之前似乎做过类似的题,翻转硬币。

2.14-T2 send \color{blue}\Diamond

赛时都差不多想到了,就是思维太固化了!

显然可以先跑一次最大费用任意流(disT<0dis_T<0 时直接 return),不在这个流中的边答案就是这个最大费用。

否则考虑强制退掉一条边的流会发生什么。容易证明流量的变化量不会超过 11。但是做到这里赛时的思路是:如果流量 +1+1,那么就相当于要选出一条 SvS\to v 和一条 uTu\to T 的最长路,并且要求两条路径在边上不交。但是不交这个条件非常难处理。

但是注意到 n,m2000n,m\le 2000,所以让 S,TS,T 为不变量反而影响了问题的解决,\color{blue}\Diamond 不如每次固定 u,vu,v 作为起点,这样可以在 S,TS,T 之间连一条虚边,然后所有的情况就都能转化成 uvu\to v 的一条路径了。后面的不是很重要。

2.17-T1 square

考虑只有两种本质不同的情况:xi<xj<xkyi<yj<ykx_i<x_j<x_k\wedge y_i<y_j<y_kxi<xj<xkyi>yk>yjx_i<x_j<x_k\wedge y_i>y_k>y_j。其他情况只需要对称一下。第一种是简单的,考虑第二种怎么算。

钦定 ci=0,cj=1,ck=2c_i=0,c_j=1,c_k=2。对 yy 坐标离散化,从左往右扫描线。考虑计算一个 jj 的答案。对于每个 yy,维护 yk=yy_k=ykk 中的 gy=minxkg_y=\min x_k,以及 yi>yky_i>y_k 中的 fy=minyixif_y=\min y_i-x_i,以及 hy=fy+gyh_y=f_y+g_y。(注意这里的 i,j,ki,j,k 要同上,即要求 xi<xj<xkx_i<x_j<x_k,下文也用 i,j,ki,j,k 表示位置关系)。

考虑做扫描线的时候会有什么影响。首先可能有一个 ck=0c_k=0kk 变成了 ii,那么 yyk,fy=min(fy,ykxk)\forall y\le y_k,f_y=\min(f_y,y_k-x_k)。然后可能有一个 ci=2c_i=2ii 变成了 kk,那么 gyi=nxtig_{y_i}=nxt_i,其中 nxti=minxp>xiyp=yixpnxt_i=\min\limits_{x_p>x_i\wedge y_p=y_i}x_p

于是需要维护的就是区间 fyf_ymin\min,单点 gyg_y 修改,并且到前者可以变成二分后区间赋值。可以直接线段树维护,因为区间赋值时 fyf_y 全部相同,那么线段树端点上就一定有 hu=fu+guh_u=f_u+g_u,直接维护就行。

2.17-T2 xor \color{blue}\Diamond

首先容易发现最后 aia_i 的值为 aijSaj(S[1,i1])a_i\oplus\bigoplus_{j\in S}a_j(S\subseteq[1,i-1])。构造考虑每个 SS 中的元素表示成 [j,i1][j,i-1] 去掉 [j+1,i1][j+1,i-1],而 aiai[,i1]a_i\leftarrow a_i\oplus [*,i-1] 是简单的,并且操作完后倒序进行前面的操作就可以还原。从大到小构造所有 aia_i 即可。

那么此时就有了一个 O(n2logV)O(n^2\log V) 的做法。设 dpi,jdp_{i,j} 表示前 ii 个,选了长为 jj 的子序列,子序列最后一个数的最小值为 dpi,jdp_{i,j}。转移只用求出来在 {akk<i}\{a_k|k<i\} 中选若干个数异或起来再 ai\oplus a_i ,使得这个值 >dpi,j>dp_{i,j} 且尽可能小。\color{blue}\Diamond 求这个值只需要让 aia_i 与线性基无交(类似 rebuild)然后再按位贪心。

考虑优化。不难发现线性基只会变化 O(logV)O(\log V) 次。如果将 aia_i 插入线性基后,线性基没有变化,则这个 aia_i 最后的取值为在 {akki}\{a_k|k\le i\} 选若干个异或起来。再考虑如果连续的一段都是这样的,或者只有开头有限制,那么若其中选的第一数在线性基能组成的数中排名为 xx,则后面的数依次是 x+1,x+2,x+1,x+2,\cdots,于是可以单调队列维护这一部分的转移。

这是 O(nlog2V)O(n\log^2V) 的。单 log\log 的如果我没退役就有极小概率补。

2.19-T2 seq \color{blue}\Diamond

注意到一个重要的限制是 pi=d\bigoplus p_i=d,这个限制没有什么很好的处理方法,\color{blue}\Diamond 不过可以考虑某些情况下,有一个 pip_i 可以任意取,那么只用确定其他的 pip_i,最后再用这个满足限制。

然后还要考虑一下如果已知 pip_i 怎么求 Si,piS_{i,p_i}。令 xipix_i\oplus p_i 最高的为 11 的位为 aia_i,那么若 xix_i 在这一位上为 00,则显然 pi>xip_i>x_iSi,pi=0S_{i,p_i}=0(这也会使得后面的 \prod00)。否则容易发现 Si,piS_{i,p_i} 的值为生成序列时 lowbit(x)=2ai\operatorname{lowbit}(x)=2^{a_i} 时,对应的 x×(xv)x\times(x\oplus v)

现在就可以尝试解决询问了。注意到如果 maxai\max a_i 要小于 dicxid\oplus\bigoplus_{i\le c}x_i 的最高位的 11 的位置,那么这个位置上就一定不满足 dd 的条件。这启示我们关注 maxai\max a_i

然后就能发现一个非常厉害的性质:当我们确定了 maxai\max a_i 及对应的 ii 之后,由于此时 Si,piS_{i,p_i} 已经确定了,就能如上文,aia_i 之后的位可以先把其它的都确定了,再用 pip_i 满足 dd 的限制。而又知道 aia_i 之前的位,pip_i 都是和 xix_i 相同的,那么就只需要使 aia_i 这一位满足 dd 的限制就行了。

于是考虑预处理 fl,r,i,0/1f_{l,r,i,0/1} 表示 [l,r][l,r] 内的序列,maxaj=i\max a_j=i,并且选了奇数/偶数个 aj=ia_j=i 的位置的方案数。转移懒得说,反正好推并且还不是正解。那么询问就可以枚举第一个 maxai\max a_i 的位置,答案即为 icjk<jf1,i1,k,0/1×fi,c,j,0/1\sum_{i\le c}\sum_j \sum_{k<j}f_{1,i-1,k,0/1}\times f_{i,c,j,0/1}0/10/1 要根据 jj 和上面最高位 11 的位置判断。最后可以做到 O((n+q)nlogV)O((n+q)n\log V)

考虑优化,发现枚举这个 maxai\max a_i 的位置没有意义,不如从前往后推,维护 fi,0/1f_{i,0/1} 表示 maxaj=i\max a_j=i 且其数量为奇数/偶数的方案数。考虑往后面加入一个序列,ff 怎么变化。设 gig_i 表示 aj=ia_j=i 时的所有方案之和,那么转移即为 fi,0fi,0×j<igj+fi,1×gi,fi,1fi,1×j<igj+fi,0×gif_{i,0}\leftarrow f_{i,0}\times \sum_{j<i}g_j+f_{i,1}\times g_i,f_{i,1}\leftarrow f_{i,1}\times \sum_{j<i}g_j+f_{i,0}\times g_i。此外还要加上 maxai\max a_i 在这一位的贡献,即为前面所有序列的 j<igj\prod\sum_{j<i}g_j 再乘上这里的 gi2i\frac{g_i}{2^i}。最后统计答案也是简单的。复杂度 O((n+q)logV)O((n+q)\log V)

2.20-T2 double \color{blue}\Diamond

容易发现算 E(ci)E(c_i) 不如算 E(bi)E(b_i) 再前缀和。\color{blue}\DiamondE(bi)E(b_i) 一个主要问题是排序,那么考虑经典套路 E(x)=iP(xi)E(x)=\sum_iP(x\ge i),于是变成算 jP(bij)\sum_jP(b_i\ge j)。又有 P(bij)=P([bij]ni+1)P(b_i\ge j)=P(\sum[b_i\ge j]\ge n-i+1),于是要算的就是有至少 ni+1n-i+1bijb_i\ge j 的方案数。(这个可以直接在排序前的 bib_i 算)

考虑这个怎么算。至少是难算的,但是可以变成恰好,恰好又能从钦定过来。于是先算钦定有 iibijb_i\ge j 的方案数,这里不同的钦定算不同的方案。这个可以插板,令其为 fi,j=(ni)×(m(j1)×in)f_{i,j}=\binom ni\times\binom{m-(j-1)\times i}n。然后可以 n2n^2 二项式反演得到恰好的 gi,jg_{i,j},再后缀和就能得到至少的 hi,jh_{i,j} 了。

但是这个复杂度大概是 n3n^3 的,不能接受。不过注意到二项式反演和后缀和的转移和系数之类,包括最后的答案都之和 ii 有关,于是直接把所有 jj 并起来一起做,就能 O(n2+mlogm)O(n^2+m\log m) 解决了。

2.21-T1 thefall \color{blue}\Diamond

我觉得这个题很有意思啊!

首先不难发现弱点击破之后一定会不断用 maxb\max b 打直到击败,所以只关心击破时的选择。先考虑一个暴力的 O(nc2)O(nc^2) dp:设 dpi,jdp_{i,j} 表示当前削韧值和为 ii,已经攻击了 jj 次的最大消耗血量,背包转移即可。

然后非常有意思的是,\color{blue}\Diamond 为了简化这个状态,可以考虑把已经攻击的 jj 次算到后面的 maxb\max b 头上,这样就能将一次攻击转化成消耗血量 maxbi-\max b_i,从而去掉一维,变成 O(nc)O(nc) 了。

2.21-T2 cruising

看到这个加删边操作,首先可能想到线段树分治。但是这样很难处理询问,除了线段树分治又没有什么方便解决这个问题的方法。怎么办!观察到数据范围 10510^5,那就暴力一点,直接对 mm 操作分块!

然后发现要对于点编号轴上的前后缀维护并查集,每次暴力枚举 O(B)O(B) 条边合并后处理询问再撤销。这可以直接用可持久化并查集实现,但是太粪了并且两个 log\log。怎么办!发现可以再离线下来扫描线,动态维护当前前缀并查集,就能 O((n+q)mlogn)O((n+q)\sqrt m\log n) 了!

然后去掉 log\log 也是简单的。容易发现固定一段前缀的并查集后,实际上可能合并的点只有 O(B)O(B) 个,所以直接新开一个并查集直接维护,就不用撤销了。