两个数列

两个数列

有两个正整数数列 $a_{1},a_{2}, \dots ,a_{n}$ 和 $b_{1},b_{2}, \dots ,b_{n}$。

现在,已知的信息有:

  1. 数列 $a$ 的各个元素的值。
  2. 数列 $b$ 的各个元素之和 $s$。
  3. 对于任意的 $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/

posted @ 2022-03-20 11:48  onlyblues  阅读(104)  评论(0编辑  收藏  举报
Web Analytics