record 3.18-3.23
让我们约定一些记号。
! 表示这个题很好/有一些有想法的点,* 表示这个题看了 sol,? 表示有疑问/仍需深入的点。
*? [1st ucup stage 0] J
场上没有花太多时间想这个。
sol 说我们把绝对值拆开,变成 \(i-a_i=j-a_j\) 和 \(i+a_i=j+a_j\)。这一步还比较常规。
我们考虑怎么去描述两个点可以匹配这件事。一个自然的想法是我们把这些数建成若干个点,然后把原图当中的点当成一条从左部连向右部的边,这样,有公共点的两条边就是可以匹配的,我们用较少的点边数描述了这个事情。
接下来我们考虑怎么匹配。你把每个连通块单独考虑,首先这个连通块一定含有偶数条边。对于一个这样的连通块,我们考虑 dfs 树,从下往上贪心,如果它向下连的边有偶数条,我们让它们内部匹配,否则把向父亲的树边拉进来匹配。这样,因为一共有偶数条边,所以到最后一定能匹配完。
通过跟 spx 的讨论(他教我),得到了另外一个可能是对的做法。我们来说一下这个思考过程。
大概还是先把绝对值拆开,然后发现这是若干个团连起来,但是每个点最多属于两个团。
其实这个时候就可以建出一个类似于圆方树的结构,得到跟上面本质相同的做法。
不过我们可以继续做。spx 首先观察到每个连通块都必须是偶数,然后他想先把偶数团给消一下,奇数团也消一下剩一个点之类的,但是消的过程要满足一些条件,很不好做。
这个时候我们注意到,上面的做法当中利用了 dfs 生成树。我们对当前这个图也取出一个 dfs 生成树,然后考虑一个剥叶子的操作。
注意到一个树可以被剥叶子剥完,当且仅当每个点的儿子当中,至多有一个 sz 是奇数,并且这个树 sz 是偶数。
由于每个点最多在两个团里面,所以这是个二叉树。
我们考虑这个点 sz 是偶数的话,它的两个孩子一定一奇一偶,对于偶数我们当成子问题,对于奇数我们把它跟根匹配。
如果这个点 sz 是奇数,它的根 \(u\) 一定已经跟某个 \(x\) 匹配过了,它的两个孩子可能是两个偶数,可能是两个奇数。如果是两个偶数,我们递归下去。如果是两个奇数,我们发现,\(u\) 和 \(x\) 在一个团里,而
\(u\) 又有两个孩子,而 \(u\) 又最多只能在两个团里,所以两个孩子里一定有一个跟 \(x\) 还有边,我们把 \(x\) 改成跟它匹配,然后 \(u\) 跟另一个孩子匹配。
这里可能还有一些思考的方法可以挖掘。
? 一个取模还原分数算法
https://www.luogu.com/article/nc5y3n87
没看懂。
[1st ucup stage 0] E
爵士好题!
我们注意到每层其实是互相独立的。因此我们可以考虑一层怎么做。
为了做 \(dep=x\) 的,我们可以做 \(dp_u\) 表示解决 \(u\) 子树内的要花多少。转移非常简单。
问题是太慢了。这个时候有两个优化方向。
一个是我们把这么多次 dp 合起来做。\(dp_{u,x}\) 表示解决 \(u\) 子树内 \(dep=x\) 的要花多少,写一下发现是个长剖优化的形式,做就完了。
另一个是优化单次 dp 的复杂度。简单来说就是考虑虚树。
其实本质上都是观察到每层独立之后,自下而上贪心。
*? CF1943 D1&D2
我糖丸了。
场上感觉 \(a,b,c\) 满足 \(b\le a+c\) 肯定是必要的,然后我构了一个 \(1,1000,1\) 认为把自己卡了???
事实上上面这个条件是充要的。证明可以考虑归纳法,我们对整个数列的和进行归纳即可。
然后我们直接进行 \(dp_{i,x,y}\) 表示 \(a_{i-1}=x,a_i=y\) 的一个方案数,做一个前缀和就可以做到 \(O(n^3)\) 了。
怎么做到 \(O(n^2)\) 呢?
我们打表观察到,对于 \(x\le y\) 的情况,\(dp_{i,x,y}\) 的值都是相等的,所以我们可以只记一个。
对于 \(x>y\) 的呢?我们发现,它们转移到 \(dp_{i+1,y,*}\) 的系数是相同的,也就是说,它们总是都能以 \(1\) 的系数转移到后面,那么我们可以只记录这些东西的和。
这样就可以做到 \(O(n^2)\) 了。
同时这个 sol 又给了另外一种做法。
我们考虑做一个容斥,钦定 \(x\) 个位置不满足条件,然后二项式反演之后答案就是 \(\sum(-1)^if_i\)。
然后记 \(dp_{i,v,x}\) 表示 \(a_i=v\),并且之前有 \(x\) 个位置钦定不满足条件的方案数。
注意到我们只关心 \(x\) 的奇偶性,所以总状态数是 \(O(n^2)\) 的,我们转移的时候考虑 \(i-2\) 位置上填的是什么就可以了。
? 一个题
给你一个包含
0,1,?的串,然后问你有多少种方法,把?改成0或者1,使得这个串是由若干偶数长度的,前一半0后一半1的串拼起来的。好像是 Topcoder 上的一个题,要求 \(O(n)\)。
首先,我们显然有一个 \(O(n^2)\) 的 dp 解法。设 \(dp_i\) 为填了前 \(i\) 个位置的方案数,我们考虑那些满足 \(j+1\sim i\) 的前一半没有 1 后一半没有 0 的 \(j\),\(dp_i\) 就是这些 \(dp_j\) 的和。
这复杂度显然是 \(O(n^2)\) 的,我们考虑优化。
你发现这个结构可以描述成,每个空格处有一个最大半径,然后 \(i\) 就是考虑那些能覆盖到 \(i\) 位置的东西,对称过去得到 \(j\)。
这东西不能做,我们考虑说得更具体一点。
你考虑一个最左侧是 1,最右侧是 0 的一个段,然后你关注这些位置 \(i\) 能取到哪些 \(j\),你大概想一下之后,发现是一些区间。所以我们做一个前缀和就好了。
好吧看起来我们想得还是不够清楚,严谨地说,这个区间是 \(O(\log n)\) 个。
我们考察 0 和 1 对问题的影响。你发现一个 0 就是限制区间长度不超过一个值,一个 1 的限制是 ban 掉一个到 \(i\) 的距离在 \([x,2x]\) 的区间。
这样的话,区间个数是 \(O(\log n)\) 个。问题是怎么找到这些区间?
静态观察比较困难,每个 1 都会产生一个区间。我们让它们动起来。随着 \(i\) 的右移,每个 1 ban 掉的位置都会单调向左扩张 \(2\) 格。而当两个区间相交的时候,我们就可以把它们合并,因为后面那个区间永远不会超过前一个区间。
现在还有另外一个问题,对于 0 的限制,我们是考虑一个后缀和。但是你发现这个询问的后缀一定是单调向右的,所以我们仍然可以均摊下来做。这个不完全对,后缀也可能向左,但是总的移动量是 \(O(n)\) 的。
这样总复杂度就是一个并查集的 \(O(n\alpha(n))\)。
当然还有另外一种 spx 给出的做法。
你考虑从前往后更新前一半全都是 ? 的区间,从后往前找前一半必须有 0 的区间。
你发现这样的话,每个部分都只是一个区间。所以我们简单前缀和一类的就可以了。
为什么会这么想呢?
mx 3.20 A
我们考虑 meet in the middle,写出来之后发现是要求一个 \(ax+by=s\) 的形式。
但是我们注意到这些数通常而言都比较大,所以我们可以考虑枚举 \(y\) 在 \(\lfloor\frac{s}{b}\rfloor\) 的范围内。这样可能有一些还不错的做法。
*? mx 3.20 C
给定 \(n,m,k\) 和一个序列 \(a_m\),定义一个长为 \(n\) 的序列是好的,当且仅当这个序列存在一个区间,这个区间的值是 \(1\sim k\) 的排列。
定义一个好的序列的权值是,这个序列中,\(a_m\) 的出现次数。让你求所有好的序列的权值和。
\(m\le n\le 25000,k\le 400\)。
看起来像 \(O(nk)\)。
我现在的初步想法是,我们考虑这个好的序列的第一个是排列的区间。我们考虑 acam,给一个开始的时候在哪个位置,结束的时候在哪个位置,这样剩下部分的方案数都能帮我们算出来了。
一个想法是给判断排列也构造一个自动机出来。可惜构不出来。
一个想法是,我们去做一些容斥,相当于钦定一些位置必须是/不是排列一类的,但是这个并不好做;不过钦定一些位置是 \(a_m\) 是好做的,但是这么做似乎没什么用。
呃呃学习了一下 spx。
这个钦定一些位置是/不是排列,其实是可以做的。具体来说,我们可以做钦定一些位置是排列。
这是怎么思考出来的呢?
我们注意到 \(m=1,a_1=1\) 的情形就是计数好的序列个数,所以我们先考虑怎么做这个。
反过来,数不好的序列个数。那么我们可以钦定 \(c\) 个位置是好的,然后带一个 \((-1)^c\)。
然后就是钦定一些位置是排列,这本质上相当于钦定一些团,有连边的不能相同。我们从前到后依次确定每个数是谁,你发现一个位置的答案跟覆盖这个位置的最前区间有关。总之我们可以做。
然后考虑 \(dp_i\) 表示我们已经钦定 \([i-k+1,i]\) 是排列的容斥系数和。转移枚举上一次钦定在哪里,根据有没有交分讨一下就可以转移了。复杂度 \(O(nk)\)。
然后考虑怎么做带权。
我们考虑钦定一个位置是 \(a\),然后去做。直接做复杂度是 \(O(n^2k)\) 的。
但是我们注意到如果 \(m>k\),这说明左右两半不会互相影响,我们可以做到 \(O(nk)\)。
mx 3.20 D
给一个 \(n\times m\) 的只包含
?,B,W的网格,你要把?填了,然后问你最多能得到多少个BW WB WB BW要求 \(O(nm)\)。
如果我们把 \(i+j\) 为奇数位置的 \((i,j)\) 的情况 flip 一下,问题变成最多能得到多少个同色小方块。
一个 naive 的想法是我们能不能从周围往中间去贪心一类地填,但是发现有点困难,也不一定做不了。
我有点想转化成一个图论/流模型。嗯嗯好像可以,我们考虑变成二者取一式,然后现在就是说,如果某四个点选了同一边,我们就可以获得 \(1\) 的收益。那不就做完了。
好的跟 spx 交流之后我们有了另一种做法。
你把每个小方块当成一个点,然后小方块有两种取法,还会有一些矛盾,最后剩下多少个小方块就是多少。
为啥别人网络流都过了就我 TLE???
* QOJ 8009
我们最朴素的想法是 \(dp_{i,x}\) 表示第 \(i\) 个数是 \(x\) 的方案数。转移用前缀和可以做到 \(O(nv)\)。
转念一想,我们关注的是最后 \(dp_{i,*}\) 的和,考虑从后往前递推每一项的系数。
看了 sol。我们好像可以考虑一个多项式。
如果我们认为 \(dp_{i,x}\) 是一个关于 \(x\) 的多项式的话,你观察一下状态转移方程。
我们设 \(dp_i(x)=\sum_{k=0}^{deg}a_kx^k\)
\(dp_{i,x}=\sum_{2y\le x}dp_{i-1,y}=\sum_{2y\le x}\sum_{k=0}^{deg}a_ky^k=\sum_{k=0}^{deg}a_k\sum_{2y\le x}y^k\)。
而由我们熟知的结论,后面这个求和是 \(k+1\) 次的多项式。所以这个东西还是 \(k+1\) 次的多项式。
我们可以插值就做完了。
另一个题
小明和 \(n\) 个人玩游戏,小明抛一个正面是 \(a\) 背面是 \(b\) 的硬币,剩下每个人抛一个六面写有 \(a_{i,1},\dots,a_{i,6}\) 的骰子。如果第 \(i\) 个人的数不超过小明的数,小明得 \(k_i\) 分。
现在小明可以选择自己的 \(a,b\),但要预付 \(ab\) 分作为代价。问他的期望最大是多少。
\(n\le 10^5\)。
我们考虑小明抛硬币的结果是 \(x\) 时的得分。你发现其实就是把每个人的数排序,然后比它小的每个人会贡献 \(\frac 16 k_i\),我们先做一个前缀和。现在相当于有一个数组 \(f_x\) 表示此时的期望得分。
我们要找到两个数 \(a,b\) 使得 \(\frac{f_a+f_b}2-ab\) 最大。考虑枚举一个 \(a\) 去找最好的 \(b\),你发现这是一次函数的形式,怎么做都可以。
其他的题
给定 \(k,b\),好看数 \(x\) 定义为满足 \(x\times(10^k-1)\) 十进制数码没有 \(b\) 的数。问从小到大第 \(m\) 个好看数是多少。
\(m\le 10^{18}\)。
这种找 \(k\) 大的,通常而言有如下几种做法:
我们把凑出答案的过程拆成若干个阶段,每个阶段有若干个选择,然后我们考虑每个选择后面有多少个解,找到最大的那个解个数不超过 \(k\) 的。(这要求你的比较必须是类似字典序比较)
或者,如果每个答案都可以从之前的答案扩展出来,并且扩展出的答案一定更大,那么我们可以把初始的点都扔到优先队列里,然后每次扩展。
或者说,如果我们能够从第 \(i\) 大的答案给出第 \(i+1\) 大的答案,那么我们可以一个个挪过去。
不过后面两种方法复杂度起码都是 \(O(k)\) 的,我们这里显然不能使用。我们考虑第一种方法。
我们考虑找是 \(10^k-1\) 的倍数,不含 \(b\) 的第 \(m\) 大数。
[ucup stage 2] E
我们先进行一个点的缩,然后就变成了一棵树,每个点里有若干个点,然后要加上一些边,使得最后整个树缩成一个点。
我们考察整个树能缩成一个点的充要条件,发现是每个边至少要被覆盖过一次,哪怕是被重边覆盖。
这就很好。我们考虑容斥,钦定一些边不能被覆盖。考虑 \(dp_{u,i}\) 表示目前已知 \(u\) 往上第一个被钦定的边深度为 \(i\) 的前提下,\(u\) 子树内的容斥系数之和。转移随便转转,总复杂度 \(O(n^2)\)。
如果我们不加 \(i\) 这一维的话,相当于只能默认上面的边都没有被钦定过。这时如果我们新钦定一条边的话,贡献不好算。
呃呃上面的当我在瞎说,这个没考虑横叉边的情况。
为了考虑进来横叉边,我们可以记录 \(dp_{u,x}\) 表示 \(u\) 子树内目前还跟自己在一个连通块内的有 \(x\) 个点。这样我们仍然可以做一个类似的 dp。
? [ucup stage 2] F
首先子矩形个数是 \(\frac{n(n+1)m(m+1)}{4}\),可以用这个判无解。
然后我们最简单的一个想法就是用一些 \(a\times b\) 的 pure rectangle 来覆盖这个矩形的某些部分,正好去拼出来相等。总之就是猜一下这个用来构造的 pattern 不会太复杂。
然后你就可以猜一些常见的 pattern 了。我先猜了一个把整个大长方形划分成 \(a\times b\) 个大小相同的块,然后块交替填 \(01\)。
你写一下,如果块大小是 \(a\times b\),那么 pure 的个数是 \(\frac{nm(a+1)(b+1)}{4}\)。
化简一下发现要求 \(2(a+1)(b+1)=(n+1)(m+1)\)。如果 \(n,m\) 当中存在奇数,那么我们已经做完了。比如 \(n=2k-1\),那么相当于是 \(2(a+1)(b+1)=2k(m+1)\),我们取 \(a=k-1\) 就可以了。嗯好像不行。
啊但是经过一些观察我们发现,好像大家都有一个解是先填一个 \(1\times m\) 的,然后重复 \(n\) 次。
然后你猜大家都有这个解。你的 \(1\times m\) 的填法是 \(a_k\)。
一通化简之后,发现要求 \((\sum a_i)^2=2\sum a_i^2+\sum a_i\),这咋做呢?
你发现这个时候我们可以贪心,每次找一个最大的能填的数填一下,然后 \(n\) 小的时候可能有一些特殊情况,我们写成一个搜的形式就可以了。
* [ucup stage 2] G
啊啊这个东西我之前是不是见过。有个 open cup 题叫 Wind of Change。
我们考虑对两个树都进行点分治。然后你在两棵树上同时枚举 \(a\) 的祖先、\(b\) 的祖先,这个复杂度是 \(O(\log^2 n)\) 的。
然后你考虑怎样的点可以贡献到某个祖先对。具体来说,我们关注一个点 \(x\) 能贡献到哪里。我们发现一个 \(x\) 能贡献到的也就是它在两个树上的祖先,也就是说仍然是 \(\log^2 n\) 个。所有能产生贡献的对是 \(O(n\log^2 n)\) 个。
不过 \(5\times 10^5\) 是不是有点危险。
好的我们看了 sol 之后得到了一个 \(O(n\log n+q)\) 的高贵做法。
简单来说,我们考虑离线,然后在第一棵树上 dfs \(a\),这样相当于每个点额外挂了一个点值 \(dis_1(a,x)\),然后我们要找距离 \(b\) 最远的一个点。这个我们可以用线段树维护直径,每次移动 \(a\) 相当于是区间的 \(dis_1(a,x)\) 进行加减。
* [ucup stage 2] H
注意不到,满足条件的 \((P,Q)\) 必须有相同的最小循环节。
首先这个条件显然是充分的。接下来我们尝试说明必要性。
首先我们来说明一下,回文串的 border 是回文串。这个过于简单,我们略去。
然后说明,回文串的循环节,一定是整循环节。我们假设串 \(S\) 有循环节 \(T\),而 \(T\) 不是整的,最后留下了一个前缀 \(P\)。举个简单的例子就是 \(S=T+T+P\)。
因为 \(S\) 是回文串,所以 \(P=P^{-1}\),\(P\) 也是回文串,然后你发现这个 \(S\) 有一个更长的 border,就有一个更短的循环节。所以就矛盾了。
接下来假设两个串 \(P,Q\) 分别是 \(P=aS,Q=bT\),\(S\neq T\)。
如果 \(|S|=|T|\) 那我们已经证完了。不妨假设 \(|S|<|T|\),对称过去,发现 \(T\) 有一个更小的 border,就有一个更小的循环节。寄了。
所以我们只需要求出来每个回文串的循环节,把相同的进行一个拼接就可以了。求出每个本质不同回文串可以使用 manacher 或者 PAM。
mx noi r1 A
我们发现,相当于是给每个人找一个点 \(f_i\),然后连出一堆置换环(链)出来。每个朋友边可以带来 \(1\) 的贡献,非朋友边带来 \(-1\) 贡献。
这个一看就想匹配一下对吧。唯一的问题出在,如果匹配之后,剩下一个孤立点,并且别的所有点都已经成环,这时这个点会带来 \(-3\) 的额外贡献而不是 \(-1\)。
现在这个解是 \(n-4\) 的,有没有可能能优化呢?当然不可能,因为跟这个点相连的两条边一定会带来 \(-1\) 的贡献。
那接下来我们只需要求出方案,看看是不是这一种情况就可以了。
* mx noi r1 B
我们是不是肯定要先会做 \(m=0\) 的情况。
你考虑我们贪心的想法就是,让帕鲁在你睡觉的时候一直干活。我们考虑一个工作 \(t\bmod d\) 的结果,按照这个分类,每一类工作都是等价的。
啊啊读错题了。我们并不能改变工作的顺序。
我们考虑 \(dp_{i,j}\) 表示前 \(i\) 个工作在 \(j\) 时刻完成的代价。我们显然可以写出一个 dp 出来,但是这个太逊了。
一个比较自然的想法是,我们考察答案当中一个连续段,这里在睡觉的时候结束的工作被认为是断点。然后你比方说记一个 \(f_{i,j}\) 表示考虑了前 \(i\) 个工作,第 \(i\) 个工作在 \(Dj\) 时刻完成的最小代价,转移的话考虑找一个连续段,然后我们的代价是显然的。最后考虑把那些剩下的代价,每 \(d\) 个消掉一个循环节就可以了。
感觉,有很多地方没说清楚。
? uoj 的一个题
arc068F
你可以把 \(1\sim n\) 按顺序选择插到 deque 的左/右侧,然后你要生成一个排列 \(a\),每次可以选择从 deque 的左/右侧取出一个数。问有多少种不同的 \(a\)。
这个我们发现,如果 \(a\) 的开头是 \(x\),不妨假设 \(x\) 在 deque 的左侧,那么 \(x+1\sim n\) 都在 deque 的另一侧。
也就是说,每个数可以选择填一个更小的数,或者选择填没填过的最大的一个数。
具体来说,一个 \(a\) 是合法的,当且仅当,它的每个位置,或者是 \(a\) 的前缀最小值,或者是 \(a\) 的后缀最大值。
设计 \(dp_{i,j}\) 表示考虑前 \(i\) 个数,目前的最小值是 \(j\) 的方案数即可。
同时这个做法可能可以给出一个 \(a\) 计算有多少个 deque 可以生成这个。
具体来说,我们考查每个位置是前缀最小值/后缀最大值,如果两者都是,说明它可以在 deque 的两侧中任意一侧,这就带来一次决策。
mx noi r1 C
这个首先有个 \(n^2\) 沙波 dp。
然后我们考虑进行一个优化。你进行一些方程的解,发现比方说 \(i\) 这个人接了,上一个接的人是 \(j\),然后解出来 \(j\) 这个人扔的初速度应该是 \(v=\min(\sqrt{lim_i-2x},v_j)\),其中 \(x\) 是两人距离。
然后你肯定分讨把最小值拆掉,分讨的结果肯定就是两个区间而已。
然后一个部分是 \(t=\sqrt{lim_i}-\sqrt{lim_i-2(h_i-h_j)}\)。你把 \(lim_i-2h_i\) 当成未知数,别的东西当成常数,发现这就是个 \(c_1+\sqrt{c_2+x}\) 的形式,这个东西,是有一个单调性的。
这个单调性应该叫,如果一开始 \(i\) 比 \(j\) 小,后来 \(i\) 把 \(j\) 超了,那么之后 \(i\) 就一直把 \(j\) 超了。或者说两个函数最多有一个交点。这东西应该是对的。
有了这个之后,我们就可以做李超树了。
另外一个部分是 \(t=\sqrt{v_j^2+2(h_i-h_j)}-v_j\),也可以写成一样的形式。
总而言之,这就是李超树,总复杂度 2log。
* mx noi r2 A
最废物的一场。
我们考虑搜索,每个位置是 ?,1,0。
考虑依次进行每个操作,如果都不是问号就进行操作,否则如果是 ?0 就变成 0?,?1 变成 ?1,0?->0?,1?->?1。
如果是 ??,注意到 01 和 10 最后都会变成 01,也就是说,这两种方案最后同时可行或者同时不可行,而我们关心对 \(2\) 取模的结果,所以我们不关心这样的方案。只剩下 00,11 这两种情况。
清算复杂度,每次想让我们产生 \(2\) 个分支就会消掉两个 ?,所以总复杂度 \(O(2^{\frac n2}m)\)。
* mx noi r2 B
我们先说场上做法。
你发现每个点最多引出两个出边,我们考虑取其中一个边作为实边,另一个边作为虚边。所有实边构成若干棵内向树,我们考虑一个点能对谁造成贡献。发现首先是它自己这个实链,然后是跳了一个虚边之后,这个点到这个点跟它 lca 这一段,以及继续往上跳一个虚边的一段。这样我们得到了一个跟虚边构成的这个树形态有关的一个做法。具体来说,我们希望它长成一个类似至多只能跳 \(\log\) 个虚边就到根节点的一个东西。
那虚边是我们自己选的,我们看看能不能给个构造。如果一个点有两个出边,如果这两个点有交的话,其中一个边没有用,这个非常好。所以现在就是说这两个点没有交,那如果它们接下来也一直无交,也很好,因为我们肯定去连那个虚边更少的,所以这样就是 \(\log\) 个边。
唯一的问题出在,这两个点现在没有交,然后走了走又交上了,这东西我不会做。
然后我们考虑 sol。
其实我们往往不需要把这个图显式建出来。你考虑手玩出来能覆盖 \(i\) 的区间的要求,或者手玩出来 \(i\) 能覆盖的区间的要求。
你考虑从 \(i\) 这个区间往上考虑,每遇到一个跟它有交但是不包含的区间,你就把它并上这个区间,这正确性是显然的。直到我们遇到一个区间把当前区间覆盖了为止。
然后你考虑这个过程可以变成边,你往左连边往右连边,这就相当于一直往左/右跳,直到遇到一个覆盖了它的区间为止。这样我们只需要求出这个覆盖了它的区间之后,就可以倍增了。后者是好求的,具体来说,我们找到能到达它的区间里面最靠右的一个即可(如果存在)。
然后我们发现合法的区间的范围在这两条路径框出来的区域内,我们做一个类似于前缀和的东西就可以了。
某个题
四个长为 \(n\) 的整数序列 \(a,b,p,q\),你可以进行任意次操作,问能否把 \(a\) 变成 \(b\)。
选区间 \([l,r]\),\(1\le l\le r\le n,r\ge p_l\),然后区间 \([l,r]\) 减 \(1\)。
选区间 \([l,r]\),\(1\le l\le r\le n,l\le q_r\),然后区间 \([l,r]\) 加 \(1\)。
\(n\le 5\times 10^5\)。
这个我们首先发现 \(c_i=a_i-b_i\),你的目标是把 \(c\) 变成 \(0\)。
然后因为操作只有区间加减,所以我们套路地考虑差分数组 \(d\),你现在可以对一个位置进行减,然后对一个范围外的地方加,最后要把 \(d\) 变成 \(0\)。
你注意到,一个位置如果既被加又被减,这样相当于这个位置作为一个中转,通过它,一个点够到了原来自己够不到的点。那我们先假装自己可以把每个点通过若干个点能够到的最近位置都求了出来,接下来每个位置不会既加又减。
那现在相当于正的位置只会被减,负的位置只会被加,我们考虑一个二分图匹配,如果有完美匹配就做完了。
但是 \(n\) 太大了,所以我们考虑使用 Hall 定理判定是否有完美匹配。
具体来说,因为一个点连出去的边是一个前缀加上一个后缀,所以我们枚举前后缀,然后找所有符合这个限制的左部点之和,看看能不能左部点更大。放到二维平面上,我们只需要扫描线就可以了。
然后我们说回怎么找最近位置。最简单的方法是我们优化建图然后缩点,然后 dp。
另外一种 spx 给的做法是,我们设 \(f_i,g_i\) 分别是 \(i\) 这个前缀中的点所能到达最靠前的点,\(i\) 这个后缀中的点所能到达的最靠后的点。然后转移就是互相转移,这样会成环,那我们判断,比方说 \(f\) 走到一个 \(g\) 再走到一个 \(f\) 并没有使得结果变得更好,那我们就不走了。唉唉这为啥会是对的啊?不过我们是不是最差也可以用 dij 来转移。
CF1946F
我们考虑 \((l,r,v)\) 对不会很多,其中 \(l\) 表示起点,\(r\) 表示终点,\(v\) 表示方案数。这样的对由于要求 \(a_l\mid a_r\),所以只有 \(O(n\log n)\) 对。
那我们一次询问 \((ql,qr)\) 就是问 \(l\ge ql,r\le qr\) 的 \((l,r)\) 的 \(v\) 之和。这个我们可以离线下来扫描线解决。
问题转化成怎么去求出这些对,这也是简单的。
总复杂度 \(O(n\log^2 n)\)。

浙公网安备 33010602011771号