suxxsfe

一言(ヒトコト)

222

1

题目大意:有两个数组 \(a,b\),你可以进行恰好一次,将 \(a\) 的一段区间翻转。设所有不同的操作方法中,操作后 \(a,b\) 中相等的位置的数量之和是多少。\(n\le 5\times 10^5\)

我们考虑对于每一种 \(a_i\) 被反转到 \(j\) 位置,然后得到 \(a_i=b_j\) 的贡献单独来求。
\(a_i=b_j=x\)
将所有等于 \(x\)\(a_i\)\(b_j\),按照靠两端的距离的较小值 \(p=min(i,n-i+1)\) 排序。
对于每个 \(p_j\) 比当前这个 \(a_i\)\(p_i\) 小的 \(b_j\),会产生 \(p_i\) 的贡献。
而对于每个 \(b_j\),若有 \(c\)\(p_i\)\(p_j\) 大的 \(a_i\),会产生 \(c\cdot p_j\) 的贡献。
这两部分可以通过从后往前扫,并记录一个 \(p_i\) 的前缀和来实现。
具体实现细节见代码。

此方法中,\(a_i=b_i\) 的情况需要单独考虑(就是不需要翻转就相等),贡献为 \(\frac{n(n+1)}{2}-i\cdot (n-i+1)\)

2

题目大意:给一个数组 \(a\) 和整数 \(m\),你每次可以进行操作:将某个 \(a_i\) 加一或减一。取一个 \(x\),使得可以用最少的操作次数,让每个 \(a_i\) 都满足 \(a_i-x\)\(m\) 的倍数,输出这个最少的操作次数。\(n\le 2\times 10^5\)

问题在模 \(m\) 意义下进行,所以先给输入的数组对 \(m\) 取模,然后排序。
问题就变成了,取一个 \(0\le x<m\),使得 \(abs(a_i-x)\) 的和最小。

可以发现,\(x\) 只会取为某个 \(a_i\),否则如果 \(x\) 在两个 \(a_i\) 中间,将他向其中之一移动,答案一定不会变劣。
那么,枚举取哪个 \(a_i\),就会将数组划分为两段,一段通过加一加到 \(a_i\),一段通过减一减到 \(a_i\)
答案计算通过前缀和进行,为了实现方便,可以将数组整体复制一遍,后半部分全部加上 \(m\),形成一个长度为 \(2n\) 的数组。

3

题目大意:有一个 \(n\times n\) 的矩阵,\(a_{i,j}=i+j\),先对他进行若干次交换两行的操作,再进行若干次交换两列的操作,设此时的矩阵是 \(p\)。再对 \(p\) 进行若干次操作:每次选定两个矩阵中有的数 \(a,b\),将所有的 \(a\) 变成 \(b\),同时所有的 \(b\) 变成 \(a\)。给出最后的矩阵,要求还原出 \(p\),如果有若干 \(p\) 满足要求,给出字典序最小的一个。\(1\le n\le 1000\)

我们发现 \(p\) 的值域是 \([2,n+n]\),而出现次数为 \(k\) 的数,要么是 \(1+k\),要么是 \(n+n+1-k\)
同时,\(p\) 的每一行,每一列,都必须是一个连续的区间 \([m,m+n-1]\)
而只要是满足以上条件的矩阵,就是一个可以通过前两种操作得到的 \(p\)

那么我们先求出给出的矩阵中,出现次数为 \(1\) 的两个数,那么肯定对应 \(p\) 中最大最小的两个数,\(2\)\(n+n\)
因为要求字典序最小,我们肯定就让 \(2\) 放在前面。
此时最大最小数都确定了,根据之前的性质,每一行每一列都是连续的区间,那么就会有两行两列的数全部被确定了。
然后去找次大数和次小数的位置,会发现有一个已经固定好的交点,根据他们的位置又能确定出若干行列。
这样不断从最大、最小的数往中间来确定,最终就确定出全部 \(n+n-1\) 种数的位置。

具体实现较为繁琐,需要使用 vector 保存出现次数为 \(cnt\) 的数被确定到了哪些位置上。
复杂度 \(O(n)\)

posted @ 2025-01-25 04:17  suxxsfe  阅读(90)  评论(0)    收藏  举报