B. LuoTianyi and the Table

news/2025/2/22 15:45:48/

题目链接
Codeforces Round 872 (Div. 2)
在这里插入图片描述
Example
input

5
2 2
1 3 1 4
2 2
-1 -1 -1 -1
2 3
7 8 9 -3 10 8
3 2
4 8 -3 0 -7 1
4 3
-32030 59554 16854 -85927 68060 -64460 -79547 90932 85063 82703 -12001 38762
output
9
0
64
71
1933711
在这里插入图片描述

题目大意:

每组测试给一个n和m,随后给出nm个数。
要求将这些数放进n
m的矩阵数组中,求上述式子的最大值。
其实每次都是取矩阵(1,1)到(i,j)这个子矩阵中最大值和最小值,将最大值减去最小值即可,最后将所有的值相加。

解题思路:

因为数字放的位置不同,最后的结果可能会有变化,但会注意到每次是取矩阵中的最大值和最小值,那么就分两种情况:
1.最大值只有一个,那么最大值就应该放在(1,1)的位置,然后取max(n,m),如果行数比列数大,那么最小值就放在(2,1)的位置,否则放在(1,2)的位置,然后第二小的值放在(2,1)/(1,2)剩下的位置
2.最小值只有一个,其实情况和最大值一样,至是一开始是最小值放在(1,1)的位置!
将两种情况取最大值即可

在这里插入图片描述
这里简单推到一下,因为是取矩阵的最大值和最小值,如果最大值和最小值已经在蓝色和红色的区域,那么剩下的值就会被随机放在其他位置。但会发现,绿色区域的值,永远都是数组b里面最大值-最小值。

在这里插入图片描述
这是情况1最大值只有1,而且列数比行数多,也就是说红色区域比蓝色区域大,那么最小值会放在(1,2),如果随机取i,j,也就是紫色区域,那么从(0,0)到(i,j)的矩阵就是红蓝和橙色圈起来的,会发现该矩阵一定会包含最大值和最小值。证明结束。

反证(证明为什么如果列数比行数多,小一放在(1,2)):如果小一不放在(1,2),那么(1,2)这个子矩阵的值是 最大值-n=ans1,如果是小一放在里面 ans2=最大值-小一,明显ans1<ans2,如果小一越“远离”(1,1)那么将会有更多的子矩阵的值比该方法小。而为什么不放(2,1)原因很简单,如下图,如果放在(1,2)将会有3个子矩阵是最大值,而放在(1,2)只有2个子矩阵是最大值!

在这里插入图片描述
C++

#include <iostream>
#include <algorithm>
#define int long long
using namespace  std;
const int N = 101 * 101 +101;
int a[N];
signed main(void){int t;cin>>t;while(t--){int n,m;cin>>n>>m;for(int i=0;i<n*m;i++){scanf("%lld",&a[i]);}sort(a,a+n*m);int minans=a[0];int minans2=a[1];int maxans=a[n*m-1];int maxans2=a[n*m-2];int maxnm=max(n,m);int minnm=min(n,m);int ans=(maxnm-1)*(maxans-minans)+(minnm-1)*(maxans2-minans)+(n*m-n-m+1)*(maxans-minans);int ans2=(maxnm-1)*(maxans-minans)+(minnm-1)*(maxans-minans2)+(n*m-n-m+1)*(maxans-minans);cout<<max(ans,ans2)<<endl;}return 0;
}

C语言

#include <stdio.h>
#include <limits.h>
#define int long long
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a>b?b:a;}
signed main(void){int t;scanf("%lld",&t);while(t--){int n,m;scanf("%lld%lld",&n,&m);int minans=LLONG_MAX;int minans2=LLONG_MAX;int maxans=LLONG_MIN;int maxans2=LLONG_MIN;int maxnm=max(n,m);int minnm=min(n,m);for(int i=0;i<n*m;i++){int num;scanf("%lld",&num);if(maxans<=num) {maxans2= maxans;maxans = num;}else if(maxans2<=num)maxans2= num;if(minans>=num) {minans2=minans;minans = num;}else if(minans2>=num)minans2=num;}int ans=(maxnm-1)*(maxans-minans)+(minnm-1)*(maxans2-minans)+(n*m-n-m+1)*(maxans-minans);int ans2=(maxnm-1)*(maxans-minans)+(minnm-1)*(maxans-minans2)+(n*m-n-m+1)*(maxans-minans);printf("%lld\n",max(ans,ans2));}return 0;
}

http://www.ppmy.cn/news/63176.html

相关文章

一个文章学会使用Git

GIT版本控制系统 版本控制系统 : ​ 1.记录历史版本信息 (记录每一次修改的记录) ​ 2.方便团队相互之间协作开发 ​ … 常用的版本控制系统 cvs / svn : 集中式版本控制系统git : 分布式版本控制系统 svn git GIT工作原理 工作区 : 我们能看到的&#xff0c;并且用来写代码的…

Mybatis一级缓存详解

目录 一级缓存 一级缓存的组织 一级缓存的生命周期 一级缓存的工作流程 Cache接口的设计以及CacheKey的定义 一级缓存的性能分析 一级缓存与Spring 事务一级缓存存在的弊端 官方文档分析 Spring通过Mybatis调用数据库的过程 一级缓存 对于会话&#xff08;Session&am…

ai皮带跑偏撕裂监测算法 yolov7

ai皮带跑偏撕裂监测系统算法基于yolov7网络模型人工智能视觉技术&#xff0c;ai皮带跑偏撕裂监测算法模型自动识别现场画面中传送皮带撕裂、跑偏、偏移等情况&#xff0c;立即告警抓拍存档同步回传后台。YOLO 的核心思想就是把目标检测转变成一个回归问题&#xff0c;利用整张图…

[优雅的面试] 进程 线程 协程分的清

面试官大佬&#xff1a;小伙子&#xff0c;咱今儿个先聊聊进程线程这块的知识哈&#xff0c;就先说说进程吧。 我&#xff1a;存储在硬盘中的代码是静态文件&#xff0c;运行中的程序被称为进程。进程之间数据是相互隔离的。 一般说来&#xff0c;一个进程并不是自始至终连续不…

自动化测试真的能提效吗?怎么才能真正掌握自动化测试技巧呢?

近年来&#xff0c;随着软件开发速度的提高&#xff0c;自动化测试已经成为了一个必要的环节。但是&#xff0c;对于自动化测试&#xff0c;有些人认为它能够大幅提升效率&#xff0c;而有些人则认为自动化测试无法替代手工测试&#xff0c;并且实施自动化测试需要投入大量的时…

【rust】| 02——语法基础_变量(不可变?)和常量

系列文章目录 【rust】| 00——开发环境搭建 【rust】| 01——编译并运行第一个rust程序 【rust】| 02——语法基础_变量(不可变?)和常量 文章目录 1. 变量1.1 变量的定义1.2 试验变量的不可变特性 2. 常量2.1 常量的定义 3. 覆盖(同名变量)3.1 修改已定义变量的数据类型3.2 1…

错排问题之年会抽奖与抄送列表

目录 一、编程题 1.年会抽奖 2.抄送列表 二、选择题 1.操作系统中关于竞争和死锁的关系下面描述正确的是&#xff1f; 2.并发是并行的不同表述&#xff0c;其原理相同。 3.在Unix系统中&#xff0c;处于()状态的进程最容易被执行。 4.当系统发生抖动&#xff08;thrashi…

为什么用循环而不用递归详解

什么是循环 循环是一种常见的编程结构&#xff0c;用于重复执行相同或类似的代码块。循环可以让程序自动处理大量数据&#xff0c;减少代码量&#xff0c;提高代码的可读性和可维护性。 循环分为三类&#xff1a;for 循环、while 循环和 do-while 循环。 for 循环是一种最常…