record 5.22-5.24

[CF1973 C]

乐,马上连 div2C 都不会了。

你发现,如果最后你要选择 \(S\) 作为答案的话,这相当于要求 \(S\) 内元素至少间隔一个位置,并且要求满足局部最大的条件。那我们显然要把最大的若干个分配给 \(S\),但是怎么分配呢?

观察样例,结合 \(n\) 是偶数的限制,我们猜测,答案就是 \(\frac{n-2}2\)。尝试进行一个构造。

首先猜测,我们选的是含有 \(n\) 的那半边。如果这半边含有 \(n\),那么我们可以把剩下的部分加和之后的结果控制在 \(n\) 以内,只需要把 \(S\) 加和控制在 \(n+1\) 以上就可以了,这个应该是容易做到的。

如果 \(n\) 出现在边缘位置,那我们可以选不会波及到 \(n\) 的那半边,然后同样可以把 \(S\) 加和控制在 \(n+1\) 以上,把剩下部分控制在 \(n\) 以内。所以就做完了。

感觉还是有点意思的。

* [CF1973 D]

哈哈,真的不会 D 了。

这个题给我们若干个 \([1,n]\) 内的数,和一个 \(k\),然后问能不能分成 \(k\) 个非空部分,使得每个部分的大小乘上最大值都是一个相同的数 \(m\),如果有,找到最大的 \(m\),如果没有,报告无解。

这个问法很神秘,你发现它不满足某种“单调性”。最大的问题是它给的信息太弱了,它只让你给 \(l,x\) 然后告诉你最小的 \(r\) 满足 \(f(l,r)=x\) 或者报告无解。事实上 \(f\) 关于 \(r\) 严格单调,所以最小的没啥用。

这个等于非常讨厌,非常弱,你随便问的话大概率是问不到任何信息的。

阅读了 sol,有点神奇。

首先我们发现检查一个 \(m\) 是不是合法这个是可以做到的,总共需要 \(k\) 次操作。那我们最多检查 \(\frac{2n}k\) 次。

\(m\)\([1,n^2]\) 的,但是我们如果知道一个最大值/大小 \(v\),就可以说 \(v\mid m\),这样就只有 \(\frac{n^2}{v}\) 种情况需要检查。但是事实上只有 \(n\) 种情况需要检查,因为只可能是 \(m=qv,q\le n\)

考虑找到最大值 \(v\),这样所有段的大小都要 \(\ge \frac mv\),要求 \(k\frac mv\le n\),也就是 \(m\le\frac{nv}k\),这就只有 \(\frac nk\) 种情况需要检查了。

问题变成怎么找到最大值。这个可以通过 \(n\) 次询问 \(1\ pn\) 找到答案。

我之前一直在想,假设我们存在一个解,然后我进行怎样的询问能一步步从前往后找到这个解。然后在想有没有可能关于 lcm 或者什么先询问出第一个位置之类的东西。其实已经发现了我们可以校验一个答案,但是没往这方面想。以及这种序列问题可能要多关注一些特殊值。

[CF1973 E]

这个题一看就很有感觉。

首先来理论上分析一波。这个 swap 关系构成等价类,所以本质上本题的要求是,每个等价类可以自洽,就是说等价类的值域和定义域要一致。换一种说法,可以说是你知道 \(x\to y\) 是需要交换的,也就是有若干个 \(x,y\) 连通的要求。每个都对 \((l,r)\) 有一些要求,取这些要求的交集就是最后的答案。

然后来分析一下等价类长成什么样子。或者分析一下 \(x,y\) 连通需要什么条件。

简单分析一下发现所有的跳跃都只可能发生在 \([l-n,r-1]\) 当中。我们直接盲猜这整个部分被连成了一个连通块,我不是很确定 corner case 对不对,所以我们写个程序跑一下。

果然不对,但是跑了 \(n=100\),corner case 只有 \(l=r\) 的情况。

\(l\neq r\) 的情况我们基本都清楚了。问题变成 \(l=r\),这个也并不困难,因为能调整的只有 \(x+y=l\) 的对,最后加个小特判就行了。

还有一个小尾巴就是怎么证明这部分确实形成了一个连通块。

我们不妨归纳法,考虑固定一个 \(l\),然后我们先证 \([l,l+1]\),后面归纳部分是简单的。

如果 \(l\le n+1\),那我们相当于需要证明 \([1,l]\) 连通,这个可以考虑 \(x\),先变成 \(l+1-x\),再变成 \(x-1\),来证明。

如果 \(l>n+1\),我们需要证明 \([l-n,n]\) 连通,你发现跟上面类似可以证明 \(x\) 能到 \(x+1\)

~ [CF1973 F]

先试试拆成不同的质因子分别考虑。对于一个质因子而言,我们可以进行一些排序,然后相当于最后你选一个位置,在这个位置之前的,它们交不交换被固定了下来。

额阅读了一些 tip。

你发现 \(\max\limits_{i=1}^{10^8}(d(i))=768\),所以干脆直接枚举可能的 \(\gcd\)\((x,y)\)

问题变成怎么算一个对的最小 cost,这个扫一遍,然后看每个元素需不需要交换就可以了。但是这样显然不行。

那你就考虑一个元素 \((a,b)\) 的贡献,发现它存在四种状态 \((0/1,0/1)\)\((0,0)\) 就代表寄了,\((1,0/1)\) 就不产生贡献,\((0,1)\) 会产生 \(c_i\) 的贡献。我们自然想在 \((x,y)\) 变化的同时维护所有状态的改变。我不知道能不能维护,但是可能比较麻烦。

另外一个想法就是,你考虑每个元素去做贡献,那就相当于要在高维空间内做一个矩形加以及最后若干次单点求值。这个就是狄利克雷前缀和,随便做做就好了。

[ARC117 D]

看着挺吓人的,第一眼还以为是计算几何。

你分析一下,发现由于所有柱子的高度都是一样的,所以碰撞关系是双向的。那碰撞关系会形成若干段,不同段之间显然是独立的。

你考虑一段碰撞关系内部怎么做。发现如果要求第 \(i\) 次时全倒下是不好计算的,但是如果要求第 \(i\) 次时当前这栋楼没倒下,还是很好做的,换言之就是要求第 \(i\) 次地震是有用的。这要求之前所有地震都向另外一个方向倒塌。

而如果第 \(i\) 次地震是最后一次地震,那么显然这次地震需要是有用的,并且这个地震正处在这个区间的边缘位置,并且它恰好倒向合适的位置,这些都是好计算的。

那现在我们知道每个区间第 \(i\) 次地震才倒下的概率了。考虑把它们合并起来,总之还是很好合并的。

~ [ARC117 E]

跑了暴力,发现这 \(31\) 种做题的方法一共有 \(4672\) 种不同的排名。这个很寄对吧,因为我们复杂度是 \(O((T+n\log n)p)\)

考虑能不能降一降,发现可以。因为如果两种方案,某一个方案当中,相等的元素构成的等价类,是另一个方案的超集,那后面这个方案就没用了。应用这个贪心的优化之后,只剩下 \(113\) 个不同的排名,就对了。

* [ARC117 F]

相当于你有一个物品要从左运输到右边,然后每条路分属一个公司,每个人分属一个公司,每个人还有初始位置。人走自己公司的路不花钱,否则花 \(1\) 块,只有人能搬运箱子,问最少花多少。

观察不难发现,每个人 \(i\) 走的路径可以用区间 \([l,r]\) 表示,代表这个人走的路径是 \(p_i\to l\to r\),并且他会把箱子 \(l\to r\)。那我们就是要选若干个人给他们分配区间让总 cost 最小。

你可能会得到一个,设 \(dp_i\) 表示走到 \(i\) 的代价,然后枚举一个区间用 cost 最小的人覆盖它进行更新的做法。事实上这是错误的,因为同一个人可能会被用两次。考虑路分成三部分,分别属于公司 \(2,1,2\),有两个人,属于公司 \(1\) 的站在第一二段的分界处,属于公司 \(2\) 的站在二三的分界处。上述算法会让第二个人先走到开头,再走到一二分界,然后让 \(1\) 运,然后直接让 \(2\) 运,cost 是第二段的长度。但事实上你只能做到两倍第一段长度,或者两倍第二段长度,总之是一个不合法的方案。

再有就是发现下面这个 \([l,r]\) 一定是 \(1,2\) 公司交替出现的。如果我们把上面那个东西,看成每个人先走到自己的 \(l\),然后大家填一填剩下的 \(r\),那似乎可以写成一个 flow 的样子。

额似乎也不一定行。

阅读了 sol。跟我是不太一样的思路。

首先它给了一个正确的 dp,具体来说就是记录当前位置,当前由哪个颜色携带,以及它发现已经被使用过的人在两个颜色中分别是一个前缀。然后就可以转移了。\(O(n^3)\)

然后它尝试优化状态数。首先,已经被使用过的人,一定大于等于在当前位置左侧的人的个数(对每个颜色分别而言)。

然后,它发现,你最多多往后用 \(20\) 个人。这是因为,你考虑最坏情况,是蓝色全在最右侧,然后红色到处都是。唉算了说不清楚,看 sol 里的图吧。大概就是每次翻倍。写起来应该还是挺好写的。

问题是为啥我没往这方面想呢?感觉一直在想一些不算很神秘,感觉也有可能有用的东西。但是这个 dp 方法感觉就很正规。是不是应该先来一个正确的做法,然后再考虑复杂度问题。但是感觉在缺失性质的时候直接说做法不太好。不过确实有些性质是基于做法才有其价值的。感觉还是没有想到“前缀”这个性质,虽然这东西并不难想。或者换句话说,没有特别去注意这个性质。

[PKUSC2024 D1T2]

场上糖丸了,写了 \(O(V^4)\) 暴力。

做法是枚举正方形的两个相邻端点,然后旋转得到另外两个,判断一下是不是都在 \(S\) 当中。

事实上这里感受一下,显然有一些单调性可以被我们利用来降低复杂度。最简单地,你考虑固定一个端点以及另一个端点的 \(x\) 坐标,给 \(y\) 坐标变一个 \(\Delta\),然后你可以发现另外两个端点的变化是有规律的,你求出这个最大的合法 \(\Delta\) 就可以了。这样复杂度是 \(O(V^3)\)

真的做法好像需要一些类欧之类的神秘做法,我们暂且不管。

不是很有意思,并不想写。

[PKUSC2024 D1T3]

这个题目好像叫 小 N 的独立集。原题做法是一个 \(O(n^2m^4)\) 左右的,抄过来就可以获得 \(11\) 还是 \(20\) 的高分来着。

我们再写一遍吧。

其实就是 dp of dp,你考虑 \(f\) 表示强制选,\(g\) 表示强制不选的答案,发现更新是

\[f_u=val_u+\sum_v g_v\\ g_u=\sum_v\max(f_v,g_v) \]

发现了吗,我们其实不关心 \(f\) 的值,反而关心 \(\max(f,g)\)。或者你也可以理解成,我们不存 \(f\) 的值,而是存 \(f,g\) 的差值,只不过当 \(f<g\) 的时候,可以强行把 \(f\) 更新到 \(g\)

这样就有 \(g_u\le f_u\le val_u+g_u\),就把 \(f\) 的值域缩到了 \(m\),记 \(dp_{u,f,g}\),复杂度是 \(O(n\times m\times nm\times m)\) 唉反正拿不了多少分。

进一步观察发现我们只关心最后的 sum,所以可以拆贡献。你像 \(g\) 就完全没必要记了,一旦有 \(g\) 就直接更新到最后的答案里头,然后清零。复杂度我没细算。

然后 spx 说这个东西是关于 \(m\) 的多项式,你算 \(n\) 遍 dp 插值就可以做到 \(O(n^4)\)。然后用 FFT 优化可以做到 \(O(n^3\log n)\)

后面不会了。

[PKUSC2024 D2T2]

我们好奇为啥我写了个 \(O(n\sqrt{n\log n})\) 为啥过不了 2e5。感觉那几天被疯狂卡常。无聊了可能要写个看看。

你考虑把询问离线下来,然后发现如果在最前面加入一个同学,如果他的 \(l\neq 0\),那就不会发生变化,否则他会去洗澡,这会影响一些后面的同学。

首先显然的一点是,随着左端点的左移,到每个位置时当前人数是单调不降的。这是因为,人数想下降一定是因为有人觉得人太多了,那么这个人走了之后,后面就不会再改变了。

有了这个性质,我们可以声称,每个人都是从没洗澡->洗澡->不洗澡这样单调地变化,所以我们只需要每次找到所有发生变化的位置进行修改就做完了。问题转化成如何知道每个发生变化的位置。

对处在不同阶段的人分别使用数据结构维护,每次相当于要查询右侧第一个 \(\le v\) 的位置,然后需要支持后缀加,删除一个元素,激活一个元素。这个是不是简单线段树上二分就可以实现了。

总复杂度 \(O(n\log n)\),让我先写个暴力看看。

怎么写完就过了。

好像不是很有事干了,让我们写个根号看看。

根号做法就是,你直接预处理出来每块输入进去什么值之后变成啥。完了不会根号了。

~ [ARC178 C]

如果记排序后的 \(b\) 两两之间的距离为 \(d_{1,\dots,n-1}\),那么最后的和其实是 \(\sum_ii(n-i)d_i\),所以相当于每个 \(d\) 前面有一些系数,然后你要凑出来 \(x\),最后的要求是 \(\sum d\) 尽可能小。

注意到询问的值域并不大,考虑 dp。\(dp_x\) 表示凑出来 \(x\) 最小的 \(\sum d\)。转移就是考虑你加了哪个系数,复杂度 \(O(nV)\),显然是不行的。

这个本质上就是,你有无限个重量分别为 \(i(n-i)\) 的物品,然后问你填满容量为 \(V\) 的背包至少需要多少个物品。

阅读了 std 复杂度。

这个问题把重量一般化我并不清楚能不能做,但是原问题是可做的。原因在于你解不等式 \(i(n-i)\le v\) 发现最多只有 \(O(\sqrt{V})\)\(i\) 满足条件,我们只对这些数进行 dp 就可以了。

[ARC178 D]

首先你发现最后删数的时候,一定是从大往小把所有不该出现的全都删掉。

那这样能删掉 \(x\) 的要求,就相当于所有比它小的数,都必须在它的同一侧。如果对所有的 \(x\) 都满足条件,那么这个排列就是满足条件的。

我们考虑从小到大填每个数,记一个 \(dp_{i,l,r}\) 表示我们目前填到了 \(i\),然后所有填了的数构成的区间是 \([l,r]\),每次填下一个数的时候,显然要填到最右侧或者最左侧。这复杂度是 \(O(n^4)\)

然后看一眼转移发现容易前缀和一下优化到 \(O(n^3)\)

* [ARC178 E]

这个题场上通过 0 人/jy。

你考虑某一个方案下,这个特殊的蚂蚁到底能走多久。别的蚂蚁之间碰撞之后交换方向并不重要,我们只关心特殊蚂蚁发生的碰撞。不妨假设它是向左走,显然只有它左侧向右以及右侧向左的蚂蚁是有用的。不妨假设左侧有 \(n_1\) 右侧有 \(n_2\) 个。

你可以当成是所有左侧的蚂蚁以 \(2\) 的速度右移,然后所有右侧的蚂蚁左移。这样进行下去,直到一侧空了为止。不妨假设是右侧空了,接下来就是特殊蚂蚁一路向右掉出去为止。

没必要这么麻烦,蚂蚁碰撞之后交换方向可以当成没交换。所以这个过程本质上就是左右两只蚂蚁 \(x,y\) 相遇,然后某一只蚂蚁走到尽头的这么一个过程,那事实上就是某一只蚂蚁从自己的位置开始一直走走到尽头的这么个过程。

如果记 \(n=\min(n_1,n_2)\),那么你选择向左走最后的答案就是右侧第 \(n\) 只蚂蚁的答案,向右走就是左侧第 \(n\) 只。

阅读了 sol,发现它分析得比我更好一点。后面没再看了,应该都是细节的讨论问题。

[mxr16 A]

显然每个位置最后相当于是对一个区间取 max,所以我们只需要找到 \(k\) 这个位置对应的区间就可以了,那就是要找一个左端点一个右端点,我们分别一路向左/右就可以了。那这个修改似乎没什么用(不好说)。

你倒着找第一个包含 \(k\) 的操作,显然可以把这次询问挂在这个操作上,这样我们的询问就少了一维,变成只剩下 \([L,R]\) 了。

我们只考虑往左跳。你从当前区间连向上一个最近的能让你的左端点移动的区间,就可以了。这样查的时候只需要倍增一下就行了。

复杂度 1 log。感觉是巨大多东西拼起来。

愤怒卡常,写了 fread,删了一个线段树之后过了。

[mxr16 B]

感觉很困难。

我们先想一想怎么判定。大概有两个方向,一个是求出来最长的 \(k\) 间距子序列,另一个是对所有长度 \(=l+1\)\(>l+1\) 也可以)的子序列检验它们都不是 \(k\) 间距的。

我们先考虑第一个做法。记 \(dp_i\) 表示以 \(i\) 结尾的最长 \(k\) 间距子序列长度,那显然有转移 \(dp_i=\max_{|a_i-a_j|\le k}(dp_j)+1\)

这样,如果我们把当前状态看成一个由每个值不同的位置的 \(dp\) 值构成的序列,那么每次相当于是区间取 max 然后加到一个人身上。我们的目标是,往后一直填一些数,然后要保证最大值 \(\le l\)。这转化给了我们一个处理的抓手。

现在相当于你有一个长度为 \(m\) 的序列 \(dp\),不过这个序列最开始只有 \(n\) 个位置有值,别的位置全是 \(0\)。然后你每次可以选择一个数 \(x\)\(dp_x\) 会被设置为 \(\max_{i\in[x-k,x+k]}dp_i+1\)。你的目标是,填入尽可能多的数,使得最后所有位置仍然 \(\le l\)

首先,如果最开始 \(dp\) 全都相等,那我们的策略大概就是,一层层往上填,这个感觉一下应该是最优的。

然后,如果它们不相等,我的初步想法是先填一部分,然后当成全都是最大值来处理。

这是正确的,有另外一种理解的角度。考虑所有操作最后变成的那个值,我们从小到大排序,操作之间是有依赖关系的,但是只要你按照这个顺序来处理操作就不会产生依赖问题。然后我们在这里做一个截断,分成最后变成的值 \(\le mx\) 以及 \(>mx\) 两部分。显然,在处理 \(>mx\) 的部分的时候,因为所有操作最后的值都 \(>mx\),所以我们把它们都当成 \(mx\) 是不会产生问题的。

这东西感觉可以递归下去算啊。就是说你把所有 \(mx\) 位置给它分开,然后变成的子问题形如 \(\text{solve}(l,r,0/1,0/1,mx)\) 表示你要考虑 \([l,r]\) 这个区间内的结果,然后最左/右侧的 \(k\) 个部分能不能操作,以及你的值域上界是 \(mx\)。这个问题应该是可以继续递归下去的,具体来说你仍然找这个区间内的最大值,然后继续分下去,是不是就行了。

那非常好,我们的子问题个数其实只有 \(O(n)\) 个,然后每次递归之后的合并计算应该是 \(O(1)\) 的,所以唯一的问题就是找到这所有的子问题都是啥。这个感觉在线段树上做一做啥的可能就会了。

写一发看看,对了就牛了。

过了,牛牛牛。

* [mxr16 C]

你有一个圆,圆上分布着一些点,每个点有权值,圆心还有一个点,它的权值每次给出。现在你要处理若干次询问,你需要给出在边权为两点权值之差的绝对值情况下,最小生成树的大小,要求边不能在除了端点外的位置相交。

首先,你假装中心点向外面连了若干个边,你发现此时的生成树方案,一定是每个点掌管一个区间,然后这个区间本身有要求就是,它内部不能有边超过一半,诸如此类。那我们显然可以有一个大概是 \(O(n^3+qn^2)\) 左右的做法。

我猜一手最后会引起答案改变的权值其实不是很多,可能只有 \(O(n)\) 个。

猜错了,现在我们能做到 \(O(n^2)\) 个。证明考虑 \(h_i\) 把数轴分成了 \(O(n)\) 个区间,考虑 \(h_0\) 在其中一个区间内移动的时候,这所有 \(2^n\) 种方案可以被抽象为一条直线,斜率取值范围在 \([-n,n]\),所以最优的直线只有 \(O(n)\) 条,所以一共只会有 \(O(n^2)\) 个答案。

我猜我们现在应该对每个区间分别考虑。但是可能只能做到 \(O(n^4)\sim O(n^5)\),首先要解决的问题是怎么断环成链。

或者说,我们现在预处理出来了这么一个 \(cost_{l,r}\),表示不使用中间点把 \([l,r]\) 这部分连通,并且不连超过直径的边,所需要的最小代价。

看了一眼 tip,有了点感觉。你发现中间点向外的连边不超过 \(2\) 个。因为如果有 \(3\) 个边的话,那一定有 \(2\) 个在 \(h_0\) 的同一侧,我们改成让它们俩连边就行了。

额所以现在每个区间其实只有 \(O(1)\) 条直线,所以一共只有 \(O(n)\) 个答案。后面好像就是一些简单的枚举一类的东西。

唉其实也不难,就是有点摆了。

[Public Round #11 A]

摆一会,来做做这个比赛,听说质量好像还行,就是不知道难度咋样。

如果我们记 \(g(x,y)\) 表示长度分别为 \(x,y\) 的随机字符串它们 \(f\) 值相等的概率,那答案就是 \(\sum_{i=1}^ng(a_i,a_{i\bmod n+1})\),也就是有 \(n\) 次 query。

我们应该先研究一下 \(f\) 的概率分布。你发现这个东西应该是有一些对称性在里头的,唯一破坏对称的部分就是如果有多个相同的位置它会去选最靠前的那一个。

事实上,你考虑一个循环节是 \(d\) 的字符串环,它会对 \(f\) 的分布产生什么影响。你发现它会给 \(1\sim d\) 加一个相等的概率。

那我们接下来有点想算循环节恰好为 \(d\) 的字符串环有多少个了。我会算循环节是 \(d\) 的因数的字符串环的个数,所以前面那个也不难预处理出来。

然后你考虑当前 query 的长度是 \((x,y)\),那你把两个 \(f\) 构建出来其实只需要 \(O(mxd(V))\) 的复杂度。包括计算也是这个复杂度。

\(V\le 10^5,mxd(V)=128\),所以总复杂度 \(O(mxd(V)n)\) 就可以过了。

? [Public Roudnd #11 B]

这怎么长得一脸 slope trick 的样子。

你先想想这个交换到底最后能交换成什么样子。如果不考虑符号的话,我们知道交换能力很强,可以直接变成任意排列。考虑符号的话,我们肯定会好奇,如果最后排列相同,是不是符号也相同。

这是正确的,你考虑 \(i\to p_i\),无论怎么交换的,牵扯到它的交换次数一定是 \(|i-p_i|+2k\) 次,所以它的符号是固定的。

同时,这样的最少操作步数显然是 \(\sum|i-p_i|\),所以我们的问题变成了找一个权值最小的合法排列 \(p\)

然后你发现两个数 \(a,b\) 不管符号的话,它们的大小关系完全由绝对值更大的那个数的符号决定。

显然,负区中的元素按照绝对值从大到小排列,正区中元素按照从小到大排列。

先考虑 \(|h|\) 互不相同的情况。

我们考虑按照绝对值从大到小的顺序依次决定每个数要放到正区还是负区,这样可以写一个 \(dp_{i,j}\) 表示目前考虑到第 \(i\) 个数,放到正区的有 \(j\) 个,然后就可以 \(O(1)\) 转移了。

看了一点 tip。

你发现代价其实是逆序对个数对吧,考虑按照合适的顺序计算逆序对。我们把一个逆序对钦定在绝对值更大的位置上计算,这样,dp 的过程中就只需要记 \(dp_{i,0/1}\) 就可以转移了,只需要使用 BIT 辅助计算逆序对。

剩下的问题是有可能 \(|h|\) 相同。相当于是问我们该怎么钦定它内部的顺序。

注意到此时外部对内部的影响其实只有一个 \(0/1\),所以我们可以把它独立成子问题来计算。

好复杂,不是很会。不想看了。

posted @ 2024-05-27 06:56  PYD1  阅读(4)  评论(0)    收藏  举报