两个数列
两个数列
有两个正整数数列 $a_{1},a_{2}, \dots ,a_{n}$ 和 $b_{1},b_{2}, \dots ,b_{n}$。
现在,已知的信息有:
- 数列 $a$ 的各个元素的值。
- 数列 $b$ 的各个元素之和 $s$。
- 对于任意的 $1 \leq i \leq n$,满足 $1 \leq b_{i} \leq a_{i}$ 成立。
利用给出的信息,我们可以对数列 $b$ 中各个元素的值进行推断。
由上述信息,我们可知对于元素 $b_{i}$,其可能的取值范围为 $\left[ {1,a_{i}} \right]$,但是受到已知条件的约束,它可能无法取到其中一些数值。
我们的任务就是计算每个 $b_{i}$ 在其可能的取值范围内,无法取到的数值的数量。
例如,如果 $n=2$,$a=\left\{4,4\right\}$,$s=8$,则数列 $b$ 中的每一个元素都不能小于 $4$(否则,另一个元素就要大于 $4$,这是不可能的),也就是说 $b_{1}$ 和 $b_{2}$ 在其可能的取值范围 $\left[ {1,4} \right]$ 内,均无法取到 $1,2,3$,无法取到的数值的数量均为 $3$。
输入格式
第一行包含两个整数 $n$ 和 $s$。
第二行包含 $n$ 个整数 $a_{1},a_{2}, \dots ,a_{n}$。
输出格式
共一行,$n$ 个整数,其中第 $i$ 个整数表示 $b_{i}$ 在其可能的取值范围内,无法取到的数值的数量。
数据范围
前三个测试点满足 $1 \leq n \leq 2$。
所有测试点满足 $1 \leq n \leq 2 \times {10}^{5}$,$n \leq s \leq \sum\limits_{i = 1}^{n}a_{i}$,$1 \leq a_{i} \leq {10}^{6}$。
输入样例1:
2 8 4 4
输出样例1:
3 3
输入样例2:
1 3 5
输出样例2:
4
输入样例3:
2 3 2 3
输出样例3:
0 1
解题思路
每个$b_{i}$是独立求解的,不需要考虑$b_{i}$与其他$b_{i}$的相关性。
首先$b_{i}$要满足$1 \leq b_{i} \leq a_{i}$。
假设所有$b_{i}$的总和为${sum}_{b}$,用${sum}_{b_{i}}$来表示除了$b_{i}$其他的$b$的和,即${sum}_{b_{i}} = {sum}_{b} - b_{i}$。同理,用${sum}_{a_{i}}$来表示除了$a_{i}$其他的$a$的和。
那么就有${sum}_{b_{i}} + b_{i} = {sum}_{b}$,$b_{i} = {sum}_{b} - {sum}_{b_{i}}$。
我们要求$b_{i}$的取值范围,那么先求${sum}_{b_{i}}$的取值范围。
由于每个都有$1 \leq b_{i} \leq a_{i}$,因此有$n-1 \leq {sum}_{b_{i}} \leq {sum}_{a_{i}} = {sum}_{a} - a_{i}$,$- \left( {sum}_{a} - a_{i} \right) \leq -{sum}_{b_{i}} \leq - \left( {n-1} \right) $,因此有$sum_{b} - \left( {sum}_{a} - a_{i} \right) \leq sum_{b} - {sum}_{b_{i}} \leq sum_{b} - \left( {n-1} \right) $。
即$sum_{b} - \left( {sum}_{a} - a_{i} \right) \leq b_{i} \leq sum_{b} - \left( {n-1} \right) $。同时$b_{i}$要满足$1 \leq b_{i} \leq a_{i}$,因此最后我们求这两个不等式的交集就可以了。
因为题目的数据范围保证每个$b_{i}$都可以取到值,因此这两个不等式一定会有交集。
AC代码如下:
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 typedef long long LL; 6 7 const int N = 2e5 + 10; 8 9 LL a[N]; 10 11 int get(LL a, LL b, LL c, LL d) { 12 return min(b, d) - max(a, c) + 1; // 两个区间的交集为左端点的最大值与右端点的最小值 13 } 14 15 int main() { 16 LL n, sb; 17 scanf("%lld %lld", &n, &sb); 18 19 LL sa = 0; 20 for (int i = 0; i < n; i++) { 21 scanf("%lld", a + i); 22 sa += a[i]; 23 } 24 25 for (int i = 0; i < n; i++) { 26 printf("%d ", a[i] - get(1, a[i], sb - (sa - a[i]), sb - (n - 1))); 27 } 28 29 return 0; 30 }
参考资料
AcWing 4315. 两个数列(AcWing杯 - 周赛):https://www.acwing.com/video/3740/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16029362.html