2 条题解

  • 1
    @ 2026-8-18 15:11:32

    有难度绝对有难度。小馋猫们别看错题了,并不会加上负数。

    首先最大的肯定在左下角或者右下角。

    偶数情况的最小的在中间两行,那奇数情况的呢?

    我本来以为一定是第一行中间的,但其实是中间三个。

    这里我们用 p1,p,p+1p - 1, p, p + 1 来指奇数情况中间的三个

    在 L 操作时,p1p - 1pp 会照顾到,且 ppp1p - 1 加的少。

    在 R 操作时,p+ 1p + 1pp 会照顾到,且 ppp+1p +1 加的少。

    那么问题来了,如果执行 R 的时候给 pp 加上了,L 啥都没干呢?

    所以要三个位置。

    那为什么奇数三个一定够呢?

    L 最多影响到第 mm 列;

    R 最少从第 mm 列开始影响(因为 xmxmx≤mx≤m)。

    受影响最小区域的左边界  m+1≤ m+1,右边界  m1≥ m−1。 因此这个最小值区间必然包含 m1mm+1m−1、m、m+1 中的某一个。

    偶数选中间两个也是同理。

    
    #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
      @ 2026-8-11 23:24:52

      解题思路

      这题目很 AT

      此题让我们求矩阵中最大值与最小值之差,那么我们就得先求出最大值和最小值(有些废话)

      我们分析一下操作。

      进行 L\texttt L 操作时第 11 列一定会被加到,而第 n+12\lfloor \frac{n+1}{2}\rfloor 列只有在 x=n+12x=\lfloor \frac{n+1}{2}\rfloor 的情况下才会加 11

      进行 R\texttt R 操作时第 nn 列一定会被加到,而第 nn+12+1n - \lfloor \frac{n+1}{2}\rfloor + 1 列只有在 x=n+12x = \lfloor \frac{n+1}{2}\rfloor 的情况下才会加 11

      进行 D\texttt D 操作时第 nn 行一定会被加到,而第 11 行只有在 x=nx=n 的情况下才会加 11

      分析完后,我们可以发现,矩阵的最大值一定是第 nn 行第 11 列的元素或者是第 nn 行第 nn 列的元素。那么就是两者的最大值。

      这个最大值也好求,就是 L\texttt L 操作的 x\sum{x}D\texttt D 操作的 x\sum{x} 的和(第 nn 行第 11 列)和 R\texttt R 操作的 x\sum{x}D\texttt D 操作的 x\sum{x} 的和(第 nn 行第 nn 列)的最大值。

      最大值算起来还算容易,最小值却没那么简单。

      首先判断有没有格子没有被操作过,条件则是如下(满足其中一者即可):

      • nn 为偶数且 L\texttt L 操作的 maxx\max x 加上 R\texttt R 操作的 maxx\max x 等于 nn
      • nn 为奇数且 L\texttt L 操作的 maxx\max x 加上 R\texttt R 操作的 maxx\max x 大于或等于 nn
      • 若上两个均不满足,则余下的最后一个条件为 D\texttt D 操作的 maxx=n\max x=n

      若满足以上条件之一,则所有格子都被覆盖了;反之有格子没被覆盖,矩阵中最小的元素为 00

      经过上面的判断,我们已经知道的矩阵是否又被全部覆盖,接下来我们得求如果是的话矩阵的最小值。

      通过前面的操作分析,我们可以进行讨论:

      • nn 为偶数且 L\texttt L 操作的 maxx\max x 加上 R\texttt R 操作的 maxx\max x 等于 nn 时,此时最小的元素应为第 11 行第 n2\frac{n}{2}n2+1\frac {n}{2} + 1 列的元素。这两个元素分别为 L\texttt L 操作时 x=n2x=\frac{n}{2} 的次数乘 11D\texttt D 操作时 x=nx=n 的次数乘 11 之和, R\texttt R 操作时 x=n2x=\frac{n}{2} 的次数乘 11D\texttt D 操作时 x=nx=n 的次数乘 11 之和,取最小值即可。
      • nn 为奇数且 L\texttt L 操作的 maxx\max x 加上 R\texttt R 操作的 maxx\max x 大于或等于 nn 时,此时会有一个特殊情况就是第 n+12\lfloor \frac{n+1}{2}\rfloor 列在 L\texttt L 操作和 R\texttt R 操作 x=n+12x=\lfloor \frac{n+1}{2}\rfloor 时都会加上 11,所以说此时第 11 行第 n+12\lfloor \frac{n+1}{2}\rfloor 列的元素不一定是最小值,所以还要考虑其左右的两个元素(样例 #2 就是一个例子)我们求出这三个元素再求最小值即可。第 11 行第 n+12\lfloor \frac{n+1}{2}\rfloor 列的元素的值为 L\texttt L 操作 x=n+12x = \lfloor \frac{n+1}{2}\rfloor 的次数乘 11 加上 R\texttt R 操作 x=n+12x = \lfloor \frac{n+1}{2}\rfloor 的次数乘 11 加上 D\texttt D 操作 x=nx=n 的次数乘 11 的值,其左右两个元素的值分别为 L\texttt L 操作 x=n+12x = \lfloor \frac{n+1}{2}\rfloor 的次数乘 22 加上 L\texttt L 操作 x=n+121x = \lfloor \frac{n+1}{2}\rfloor-1 的次数乘 11 加上 D\texttt D 操作 x=nx=n 的次数乘 11 的值,R\texttt R 操作 x=n+12x = \lfloor \frac{n+1}{2}\rfloor 的次数乘 22 加上 R\texttt R 操作 x=n+121x = \lfloor \frac{n+1}{2}\rfloor-1 的次数乘 11 加上 R\texttt R 操作 x=n+12x = \lfloor \frac{n+1}{2}\rfloor 的次数乘 11 加上 D\texttt D 操作 x=nx=n 的次数乘 11 的值。
      • 以上均不满足,且 D\texttt D 操作的 maxx=n\max{x}=n,则最小值为 D\texttt D 操作的 x=nx=n 的次数乘 11

      最后输出最大值减最小值的差即可。

      代码如下:

      #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

      [COCI 2025/2026 #4] 战斧牛排 / Tomahawk

      信息

      ID
      12630
      时间
      1000ms
      内存
      512MiB
      难度
      8
      标签
      递交数
      86
      已通过
      13
      上传者