2 条题解
-
1
有难度绝对有难度。小馋猫们别看错题了,并不会加上负数。
首先最大的肯定在左下角或者右下角。
偶数情况的最小的在中间两行,那奇数情况的呢?
我本来以为一定是第一行中间的,但其实是中间三个。
这里我们用 来指奇数情况中间的三个
在 L 操作时, 和 会照顾到,且 比 加的少。
在 R 操作时, 和 会照顾到,且 比 加的少。
那么问题来了,如果执行 R 的时候给 加上了,L 啥都没干呢?
所以要三个位置。
那为什么奇数三个一定够呢?
L 最多影响到第 列;
R 最少从第 列开始影响(因为 )。
受影响最小区域的左边界 ,右边界 。 因此这个最小值区间必然包含 中的某一个。
偶数选中间两个也是同理。
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int N = 1e5 + 10; int main () { ios::sync_with_stdio(false); cin.tie(0); int n, q; cin >> n >> q; LL mxl = 0, mxr = 0; if (n & 1) { LL mnl = 0, mnm = 0, mnr = 0; int sid = (n + 1) / 2; for (int i = 1; i <= q; i ++) { char s[5]; cin >> s; LL x; cin >> x; if (s[0] == 'L') { mxl += x; if (x >= sid - 1) { mnl += (x - (sid - 1) + 1); if (x >= sid) { mnm += (x - sid + 1); } } } if (s[0] == 'R') { mxr += x; if (x >= sid - 1) { mnr += (x - (sid - 1) + 1); if (x >= sid) { mnm += (x - sid + 1); } } } if (s[0] == 'D') { mxl += x; mxr += x; if (x == n) { mnl += (x - n + 1); mnm += (x - n + 1); mnr += (x - n + 1); } } } LL suma = max(mxl, mxr); LL sumb = min(mnl, min(mnm, mnr)); cout << suma - sumb << "\n"; } else { LL mnl = 0, mnr = 0; int sid = (n + 1) / 2; for (int i = 1; i <= q; i ++) { char s[5]; cin >> s; LL x; cin >> x; if (s[0] == 'L') { mxl += x; if (x == sid) { mnl += (x - sid + 1); } } if (s[0] == 'R') { mxr += x; if (x == sid) { mnr += (x - sid + 1); } } if (s[0] == 'D') { mxl += x; mxr += x; if (x == n) { mnl += (x - n + 1); mnr += (x - n + 1); } } } LL suma = max(mxl, mxr); LL sumb = min(mnl, mnr); cout << suma - sumb << "\n"; } return 0; } -
-1
解题思路:
这题目很 AT此题让我们求矩阵中最大值与最小值之差,那么我们就得先求出最大值和最小值(有些废话)
我们分析一下操作。
进行 操作时第 列一定会被加到,而第 列只有在 的情况下才会加 。
进行 操作时第 列一定会被加到,而第 列只有在 的情况下才会加 。
进行 操作时第 行一定会被加到,而第 行只有在 的情况下才会加 。
分析完后,我们可以发现,矩阵的最大值一定是第 行第 列的元素或者是第 行第 列的元素。那么就是两者的最大值。
这个最大值也好求,就是 操作的 与 操作的 的和(第 行第 列)和 操作的 与 操作的 的和(第 行第 列)的最大值。
最大值算起来还算容易,最小值却没那么简单。
首先判断有没有格子没有被操作过,条件则是如下(满足其中一者即可):
- 为偶数且 操作的 加上 操作的 等于 ;
- 为奇数且 操作的 加上 操作的 大于或等于 ;
- 若上两个均不满足,则余下的最后一个条件为 操作的 。
若满足以上条件之一,则所有格子都被覆盖了;反之有格子没被覆盖,矩阵中最小的元素为 。
经过上面的判断,我们已经知道的矩阵是否又被全部覆盖,接下来我们得求如果是的话矩阵的最小值。
通过前面的操作分析,我们可以进行讨论:
- 当 为偶数且 操作的 加上 操作的 等于 时,此时最小的元素应为第 行第 或 列的元素。这两个元素分别为 操作时 的次数乘 与 操作时 的次数乘 之和, 操作时 的次数乘 与 操作时 的次数乘 之和,取最小值即可。
- 当 为奇数且 操作的 加上 操作的 大于或等于 时,此时会有一个特殊情况就是第 列在 操作和 操作 时都会加上 ,所以说此时第 行第 列的元素不一定是最小值,所以还要考虑其左右的两个元素(样例 #2 就是一个例子)我们求出这三个元素再求最小值即可。第 行第 列的元素的值为 操作 的次数乘 加上 操作 的次数乘 加上 操作 的次数乘 的值,其左右两个元素的值分别为 操作 的次数乘 加上 操作 的次数乘 加上 操作 的次数乘 的值, 操作 的次数乘 加上 操作 的次数乘 加上 操作 的次数乘 加上 操作 的次数乘 的值。
- 以上均不满足,且 操作的 ,则最小值为 操作的 的次数乘 。
最后输出最大值减最小值的差即可。
代码如下:
#include <bits/stdc++.h> #define int long long using namespace std; int n, q, x, tl, tr, td, ml, mr, md; int jl, jr, jd; int pl, pr; char c; signed main () { cin >> n >> q; while (q --) { cin >> c >> x; if (c == 'L') { tl += x; if (x == (n + n % 2) / 2) jl ++; if (x == (n + n % 2) / 2 - 1) pl ++; ml = max (ml, x); } else if (c == 'R') { tr += x; if (x == (n + n % 2) / 2) jr ++; if (x == (n + n % 2) / 2 - 1) pr ++; mr = max (mr, x); } else { td += x; if (x == n) jd ++; md = max (md, x); } } int mx = max (tl + td, tr + td), mi = 0; if (n % 2 == 0 && ml + mr == n) mi = min (jl, jr) + jd; else if (n % 2 && ml + mr >= n) mi = min ({jl + jr, pl + 2 * jl, pr + 2 * jr}) + jd; else if (md == n) mi = jd; cout << mx - mi; }
- 1
信息
- ID
- 12630
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 8
- 标签
- 递交数
- 86
- 已通过
- 13
- 上传者