日常的训练,回顾一下做的几道题,实现不发
ICPC Hangzhou Reginal F Fuzzy Ranking
不太会做,看了一下题解,下面是看完题解后的思路
直接为任意“前→后”对连边会太多,在同一排列中,只连相邻元素 $a_j\to a_{j+1}$ 即可:因为一条从前往后的有向路径已经能覆盖该排列中任意“前→后”的可达关系。对所有 $k$ 个排列加边
对图做一次 Tarjan/Kosaraju缩点,得到每个学校所属的 SCC 编号bel[x],以及按拓扑序逆序排列的分量列表 scc。把每个榜单按 bel重新映射成“分量编号序列”。
在某个榜单中,原先相邻的两点之间有边,缩点后相同分量的编号在该榜单上必然连成一段。因此每个榜单都可以被切成若干段,每段恰好由同一个 SCC 的元素组成。这个性质让我们可以把任意区间 $[l,r]$ 拆解为:左端一个不完整段 + 中间若干完整段 + 右端一个不完整段。
对每个榜单i:
Segment:对位置轴进行分段。令 Segment= (L, R) 表示pos所在的那段在该榜单上的左右端点下标。线性扫,遇到一段相同编号的区间 $[L,R]$ 就把这对端点填给其中的每个位置。
dp 前缀:统计从开头到位置 $j$ 为止、同段内能形成的“模糊对”数量。若 $j$ 落在段 $[L,R]$,新增的成对数等于该段里被纳入的元素个数减一,即 $j-L$。因此定义
$$ dp[id][j] = dp[id][j-1] + (j-L). $$这样任意区间 $[x,y]$ 的“在同一段内形成的对数”就能通过 $dp$ 差分 $dp[id][y]-dp[id][x]$ 得到。
总计复杂度$O(nk)$
CF1841E Fill the Matrix
题目说有一个$n * n$的正方形矩阵,在第$i$列,前$a_i$个格子都是黑色,剩下的格子是白色,在矩阵放入1到m到整数,每个格子最多放一个且黑色格子不能放,定义美丽值为数字 $j$ 和 $j+1$ 位于同一行,且 $j+1$ 位于 $j$ 的右边相邻的格子,求放置m个整数后最大美丽值
我们一定先选一个最长的白色格子全填进去,直到填满或者数不够。因为如果不继续填等于说最后填的那个数旁边的格子就浪费了,所以关键就在于要把所有行的白色连续横段都计算出来,按长度分组,记为cnt[n],代表长度n的横段有几个,直接暴力扫迷线维护复杂度是$O(n^2)$的,直接炸了,所以我们用线段树来维护最大值和位置然后再分治来统计cnt数组,相当于构建一颗笛卡尔树,每次把区间按最大值分为左右两部分,统计每层能产生的白格段,最后用贪心计算答案就可以了,这样最后复杂度就控制在$O(nlogn)$
CF2056D Unique Median 2200
给了一个整数数组b,当排序后满足$b⌊\frac{m+1}{2}⌋=b⌈\frac{m+1}{2}⌉$时我们说数组是好的,题目说给一个长度为n的数组a,计算好子数组数量
首先观察好数组定义,我们可以很容易发现奇数长度的数组一定是好数组,所以我们只要看偶数长度的数组就可以了,很困难,想了一段时间,一开始的想法是如果我们要让偶数的数组是好的,那么当且仅当存在某个数$v$,使得在选取的子数组中$v \ge m/2$,也就是说至少一半都是同一个数,但是肯定会有重复用容斥修正,减掉重复的就可以,实现很麻烦,写了很久,而且还发现是错误的,对于[1,1,2,3]按照这个思路明显错的,而且发现正着处理非常麻烦困难,于是决定反向试试,从所有子数组中减掉"坏的",再修正
很快就发现了一些东西,对于一个偶数的数组,只要让排序后第k个数小于k+1个数一定是坏的,再具体点,我们选定两个相邻的数x,y,我们只要让左中位数小于等于x,右中位数大于等于y就可以了,然后用前缀和+map即可,并且小于等于x的数的数量和大于等于y的数字数量必须要一样多,那么我们可以把数组按照值分为3类,一种小于等于x我们记为-1,大于等于y记为+1,介于x和y之间的我们直接清空,因为出现就相当于直接破坏了我们的数组
最后就是用容斥进行修正,只要x和y相差超过2就记为重复的减掉就可以了
CF1854A2 Dual (Hard Version)
一道思维题,给了一个数组,可以对于$i,j$的元素进行操作,使得$a_i := a_i + a_j$
要求在31次操作内让数组不递减
首先当所有元素都大于等于0或者全部都小于等于0的时候很显然,我们只需要把右边的数依次加上左边的数肯定是对的(小于等于0同理反过来就行)
所以关键是要看数组里有正有负,我们设最大的正数是mx,绝对值最大的负数是mi,正数数量是cp,负数数量是cm,那么我们有两种选择,一种是都统一成非负,一种是统一成非正,只要符号统一我们就方便了,拿统一非负举例(非正同理),我们其实就是要让最大的正数足够大,能够覆盖所有负数,我们首先计算mx经过几次翻倍可以大于mi,然后让他翻倍,之后让所有的负数都加上这个mx它们都变成正数了,然后我们就判断一下这两种选择哪个更优即可
