9.4 CF1852 题解
CF1852 题解
A Ntarsis' Set
题意
有一个集合,初始状态里面有数字 \(1\)、\(2\)、\(3\)、\(4\)、\(5\)、......、\(10^{1000}\)。
现在给你一个长度为 \(n\) 数组 \(a (1\leq a_i \leq 10^9 )\),要进行 \(k\) 次操作,每次操作将当前集合中第 \(a_1\) 小、第 \(a_2\) 小、......、第 \(a_n\) 小的数同时移除。
请问 \(k\) 次操作之后,最小的数是多少。
题解
倒叙,考虑答案在每次操作的位置。
设当前位置是 \(w\)。
最后的位置一定是 \(w = 1\)。
倒数第二的位置是考虑操作序列 \(a_i \le w\) 的位置我们都会取到。
取完之前的位置 \(w = w + \sum_i^n[a_i \le w]\)。
这样是 \(O(nk)\) 的。
每次找到最后一个 \(a_{end} \le w\) ,\(w\) 是递增的,那么 \(end\) 也是递增的,就可以 \(O(n+k)\)。
B Imbalanced Arrays
题意
对于一个给定的长度为 \(n\) 的数组 \(A\),定义一个长度为 \(n\) 的数组 \(B\) 是不平衡的当且仅当以下全部条件满足:
-
\(-n \leq B_{i} \leq n\) 且 \(B_{i} \ne 0\)。即每个数在 \([-n,n]\) 内且不为 \(0\)。
-
\(\forall i,j \in [1,n], B_{i} + B_{j} \neq 0\)。即数组内不存在一对相反数。
-
\(\forall i \in [1,n], \sum_{j = 1}^{n} [ \left (B_{i} + B_{j} \right) > 0] = A_{i}\)。即对于任意的 \(i\),数组中与 \(B_{i}\) 和大于 \(0\) 的数的个数恰好为 \(A_{i}\)。注意:这里需要计算本身。也即 \(i\) 与 \(j\) 可以相等。
请构造长度为 \(n\) 的不平衡序列。
题解
考虑因为没有相反数,所以最后的数取绝对值之后是一个排列。
我们对 \(a\) 倒序排序,然后很显然大的是正数,小的是负数。
所以排序后大的在左边,小的在右边,我们需要找到这个正负的分界线。
那么界限需要满足 \(\sum_{i = 1} ^ wa_i - w^2 = \sum_{i = w + 1}^na_i\)。
因为每个正数和每个正数之间会做出 1 贡献,那么界限是 \(w\) 代表有 \(w\) 个正数,总贡献是 \(w^2\)。
剩余的贡献就是正数和负数加起来最后 \(>0\) ,正数这边的贡献要和负数这边的贡献相等才可以。
我们把界限左边部分,也就是正数的贡献 \(a_i = a_i- w\) 只考虑正数和负数的贡献。
我们把界限右边部分,也就是负数的贡献变为 \(a_i+a_j < 0\) 的贡献,那么也就是 \(a_i = n - a_i\) 。
现在负数之间也可以相互贡献,共有 \(n - w\) 个负数,每个负数和所有负数都可以相互贡献,也减去相互的贡献,只剩正数和负数相加 \(<0\) 的贡献。
现在负数的 \(a_i\) 就是 \(a_i = n - a_i - (n - w) = w - a_i\) 。
假设样例是 \(a = {4,3,2,1}\) 界限 \(w = 2\) ,变换后的 \(a\) 就是 \(a = 2,1,0,1\) 。
现在两个指正 \(l,r\) 指向 \(2,1\) 。
\(2\) 代表第一个数负数中有两个和他相加 \(>0\) ,当 \(r - w = a_l\) 时这个数一定和所有正数相加都 \(>0\),移动左指针,填 \(4\)。
当填完之后指针移动:
左边的 \(1\) 代表负数中有一个和他相加 \(>0\) ,右边的 \(1\) 代表正数中有一个和他相加 \(<0\)。
当 \(w - l + 1 = a_r\) 时这个数一定和所有正数相加都 \(<0\),移动右指针,填 \(-3\)。
这样一步一步推下去就可以了。
C Imbalanced Arrays 题解
题意
-
给定一个长度为 \(n\) 的序列 \(a\) 和正整数 \(k\)。
-
每次可以选择一个区间 \([l,r]\),\(\forall i \in [l,r],a_{i} = a_{i} -1\)。
-
如果 \(a_{i} = 0\),则将 \(a_{i}\) 变为 \(k\)。
求让序列全部为 \(k\) 的最小操作次数。
多组测试数据,\(1 \leq n \leq 2 \times 10^{5}\)。
题解
先考虑如果没有 "\(a_{i} = 0\),则将 \(a_{i}\) 变为 \(k\)",直接差分后统计所有正数加起来。
因为原序列全是正数,所以差分序列正数一定比负数多,如果一般情况原序列有正有负那么需要对正数和负数分别求和然后取 max
现在就是多一种操作,区间 \(+k\) 并且不消耗操作次数。
对应差分序列就是一个点 \(+k\),后面的一个点 \(-k\) (也有可能不减)。
显然原序列上一个负数 \(+k\), 一个正数 \(-k\) 可能让答案更优秀。
设负数是 \(a_i\) ,正数是 \(a_j(i<j)\) ,那么如果 \(a_i + k < a_j\) 就可以选。
用优先队列存负数 \(a_i\) ,遇到一个正数就取出最小的那个判断。
D Miriany and Matchstick
题意
你有一个 \(2\times n\) 的矩阵,第一行给定(字符串 \(s\)),你需要在第二行的位置填上 \(A\) 或 \(B\)。
我们定义:
-
一个 \(1\times 2\) 或 \(2\times 1\) 的子矩阵的分数为 \(1\) 当且仅当该矩阵中有且仅有一个 \(A\) 和 一个 \(B\),否则该子矩阵的分数为 \(0\)
-
一个 \(2 \times n\) 的矩阵的分数为所有的 \(1\times 2\) 和 \(2 \times 1\) 的子矩阵的分数和
你需要构造矩阵的第二行,使得该矩阵的分数恰好为 \(k\)
题解
设 \(f_{i,0/1,k}\) 代表前 \(i\) 列第 \(i\) 列选 \(A/B\) 能否满足有 \(k\) 个 \(AB\) 。
转移很简单,但这是 \(O(n^2)\) 的。
打标可以发现当前两维确定时,1 都是连续的,中间最多有 1 个缺的点,如同 00111011111。
可以维护 \(l,r\) 和缺失点 \(p\) 然后转移。