「Dasha and Photos」Solution

news/2024/5/20 15:36:33

简述题意

给定一个 n × m n \times m n×m 的方格,每个格子里有一个小写英文字母。

现在你有 k k k n × m n \times m n×m 的方格,这些方格都是给定方格的基础上将左上角为 ( a i , b i ) (a_i,b_i) (ai,bi),右下角为 ( c i , d i ) (c_i,d_i) (ci,di) 的矩形区域的方格中的字母替换成字符 e i e_i ei

定义两个方格的距离为所有格子中字母在 Ascll \text{Ascll} Ascll 码的差累和。你要找到 k k k 个方格中的一个方格,满足它到其他 k − 1 k-1 k1 个矩阵的距离之和最小,并输出这个最小值。

  • 1 ≤ n , m ≤ 1000 , 1 ≤ k ≤ 3 × 1 0 5 1 \le n,m \le 1000,1 \le k \le 3 \times 10^5 1n,m10001k3×105
  • 1 ≤ a i , b i ≤ n , 1 ≤ c i , d i ≤ m 1 \le a_i,b_i \le n,1 \le c_i,d_i\le m 1ai,bin,1ci,dim

思路

以下简记:

  • X ( a i , b i , c i , d i ) X(a_i,b_i,c_i,d_i) X(ai,bi,ci,di) 表示 X X X 矩阵的左上角为 ( a i , b i ) (a_i,b_i) (ai,bi),右下角为 ( c i , d i ) (c_i,d_i) (ci,di) 的子矩阵的元素之和
  • A A A 表示原矩阵。

首先不难想到枚举每一个矩阵,求出其到其他 k − 1 k-1 k1 个矩阵的距离和,取最小值即可,然而我们难以直接维护当前枚举到的矩阵与其他矩阵的距离和。

注意到,每一个新矩阵与原矩阵唯一的差别便是一个子矩阵不一样,套路地想到维护原矩阵。

不妨令 w i , j , k w_{i,j,k} wi,j,k k k k 个新矩阵中, ( i , j ) (i,j) (i,j) 这一位的字母为 k k k 的数量, c n t i , j cnt_{i,j} cnti,j 表示 k k k 个新矩阵中有多少个矩阵与原矩阵不同的位置包含了 ( i , j ) (i,j) (i,j)

考虑如何求出 w w w 数组。不妨先让 ∀ x ∈ [ 1 , n ] , y ∈ [ 1 , m ] , w x , y , A x , y = k \forall x \in [1,n],y \in [1,m],w_{x,y,A_{x,y}}=k x[1,n],y[1,m]wx,y,Ax,y=k,后面减去掉原矩阵贡献的这一部分即可。而后,每生成一个矩阵,就相当于把 ∀ x ∈ [ a i , b i ] , y ∈ [ c i , d i ] , w x , y , e i ← w x , y , e i + 1 , c n t x , y ← c n t x , y + 1 \forall x \in [a_i,b_i],y \in[c_i,d_i],w_{x,y,e_i} \leftarrow w_{x,y,e_i}+1,cnt_{x,y} \leftarrow cnt_{x,y}+1 x[ai,bi],y[ci,di],wx,y,eiwx,y,ei+1,cntx,ycntx,y+1,最后统一把 x ∈ [ 1 , n ] , y ∈ [ 1 , m ] , w x , y , A x , y ← w x , y , A x , y − c n t x , y x \in [1,n],y \in [1,m],w_{x,y,A_{x,y}} \leftarrow w_{x,y,A_{x,y}} - cnt_{x,y} x[1,n],y[1,m],wx,y,Ax,ywx,y,Ax,ycntx,y 即可。

有了 w w w 数组后,就可以求出原矩阵与 k k k 个新矩阵的距离和。具体地,枚举 ( i , j ) (i,j) (i,j),那么当前位置与 k k k 个矩阵对应位置的差值和即为: r e s i , j = ∑ o ∈ S w i , j , o × ∣ A i , j − o ∣ res_{i,j}=\sum_{o \in S}w_{i,j,o} \times |A_{i,j}-o| resi,j=oSwi,j,o×Ai,jo,其中 o o o 为字符, S S S 为字符集。

有了 r e s res res 数组之后就大功告成了!

而后,枚举每一个新矩阵,先继承一下原矩阵的贡献,就是 r e s ( 1 , 1 , n , m ) − r e s ( a i , b i , c i , d i ) res(1,1,n,m)-res(a_i,b_i,c_i,d_i) res(1,1,n,m)res(ai,bi,ci,di),紧接着考虑 ( a i , b i , c i , d i ) (a_i,b_i,c_i,d_i) (ai,bi,ci,di) 这个子矩阵对答案的贡献,显然就是 ∑ o ∈ S w o ( a i , b i , c i , d i ) × ∣ e i − o ∣ \sum_{o \in S}w_o(a_i,b_i,c_i,d_i) \times |e_i-o| oSwo(ai,bi,ci,di)×eio。(说人话 w o ( a i , b i , c i , d i ) w_o(a_i,b_i,c_i,d_i) wo(ai,bi,ci,di) 表示的就是 k k k 个矩阵每一个 ( a i , b i , c i , d i ) (a_i,b_i,c_i,d_i) (ai,bi,ci,di) 子矩阵中有多少个字符 o o o

总结一下,一个矩阵到其他 k − 1 k-1 k1 个矩阵的距离和即为:

r e s ( 1 , 1 , n , m ) − r e s ( a i , b i , c i , d i ) + ∑ o ∈ S w o ( a i , b i , c i , d i ) × ∣ e i − o ∣ res(1,1,n,m)-res(a_i,b_i,c_i,d_i)+\sum_{o \in S}w_o(a_i,b_i,c_i,d_i) \times |e_i-o| res(1,1,n,m)res(ai,bi,ci,di)+oSwo(ai,bi,ci,di)×eio

空间优化

如果你使用的是 区间修改,区间查询 的二维树状数组求解 w , r e s w,res w,res,那么恭喜你喜提 Memory limit exceeded on test 1 \text{Memory limit exceeded on test 1} Memory limit exceeded on test 1,因为每一个树状数组需要 4 4 4 b i t bit bit 数组,且需要 26 26 26 个这样的树状数组,空间炸飞了。

再仔细思考,发现此题的 区间修改,区间查询 不是同时进行的,所以不妨先差分,再前缀和求出每一位,再前缀和维护子矩阵的和,这样普通数组就可以解决。

代码

请自行忽略树状数组,当成差分看就行。

主要是最开始超空间限制,改了半截发现空间开得下了就懒得改了。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 1000 + 5 , MAXM = 3e5 + 5;
int n , m , k , a[MAXM] , b[MAXM] , c[MAXM] , d[MAXM];
ll Pre_T[MAXN][MAXN][26] , Pre_res[MAXN][MAXN] , res[MAXN][MAXN];
char mp[MAXN][MAXN] , opt[MAXM];
struct BIT{#define lowbit(x) (x & -x)int bit[MAXN][MAXN];void update(int k , int k2 , int x) {for (int i = k ; i <= n ; i += lowbit(i)) {for (int j = k2 ; j <= m ; j += lowbit(j)) {bit[i][j] += x;}}}ll Sum(int k , int k2) {ll sum = 0;for (int i = k ; i ; i -= lowbit(i)) {for (int j = k2 ; j ; j -= lowbit(j)) {sum += bit[i][j];}}return sum;} void add(int a , int b , int c , int d , int x) {update(a , b , x) , update(a , d + 1 , -x) , update(c + 1 , b , -x) , update(c + 1 , d + 1 , x);}
}T[27];
ll query1(int a , int b , int c , int d , int opt) {return Pre_T[c][d][opt] - Pre_T[a - 1][d][opt] - Pre_T[c][b - 1][opt] + Pre_T[a - 1][b - 1][opt];}
ll query2(int a , int b , int c , int d) {return Pre_res[c][d] - Pre_res[a - 1][d] - Pre_res[c][b - 1] + Pre_res[a - 1][b - 1];}
signed main() { ios::sync_with_stdio(false);cin.tie(nullptr) , cout.tie(nullptr);cin >> n >> m >> k;for (int i = 1 ; i <= n ; i ++) {for (int j = 1 ; j <= m ; j ++) {cin >> mp[i][j];}}for (int i = 1 ; i <= k ; i ++) {cin >> a[i] >> b[i] >> c[i] >> d[i] >> opt[i];T[opt[i] - 'a'].add(a[i] , b[i] , c[i] , d[i] , 1);T[26].add(a[i] , b[i] , c[i] , d[i] , 1);}for (int i = 1 ; i <= n ; i ++) {for (int j = 1 ; j <= m ; j ++) {int sel = T[26].Sum(i , j);T[mp[i][j] - 'a'].add(i , j , i , j , k - sel); }}for (int i = 1 ; i <= n ; i ++) {for (int j = 1 ; j <= m ; j ++) {int now = mp[i][j] - 'a';for (int o = 0 ; o < 26 ; o ++) res[i][j] += 1ll * abs(now - o) * T[o].Sum(i , j);}}for (int i = 1 ; i <= n ; i ++) {for (int j = 1 ; j <= m ; j ++) {Pre_res[i][j] = Pre_res[i - 1][j] + Pre_res[i][j - 1] - Pre_res[i - 1][j - 1] + res[i][j];for (int o = 0 ; o < 26 ; o ++) {Pre_T[i][j][o] = Pre_T[i - 1][j][o] + Pre_T[i][j - 1][o] - Pre_T[i - 1][j - 1][o] + T[o].Sum(i , j);} }}ll ans = 1e16;for (int i = 1 ; i <= k ; i ++) {int now = opt[i] - 'a';ll w = query2(1 , 1 , n , m) - query2(a[i] , b[i] , c[i] , d[i]);for (int o = 0 ; o < 26 ; o ++) w += 1ll * abs(now - o) * query1(a[i] , b[i] , c[i] , d[i] , o);ans = min(ans , w);}cout << ans;return 0;
}

http://www.mrgr.cn/p/23233872

相关文章

SpringBoot项目GraalVM迁移

一些背景 一直想把项目迁移到使用GraalVM构建出的原生应用上,但是在前段时间的一次尝试后,发现很难做到,其中一个最主要原因就在于我目前手头上没有X86架构的电脑。平时我使用的是一个M1处理器的MacBook,编译出的Docker镜像架构指令集也是Arm64的,无法在我的X86服务器启动…

Android Studio报错:Constant expression required

【出现的问题】&#xff1a; 使用JDK17以上版本&#xff0c;switch语句报错&#xff1a;Constant expression required 【解决方法】&#xff1a; 在gradle.properties配置文件下添加代码&#xff1a; android.nonFinalResIdsfalse 如图&#xff1a; 接着再点击右上角的Sync…

国内验签SSL证书——数据不出境,政务、高校、金融机构必备

涉及金融、政务、教育等重要领域的网站&#xff0c;国家要求是重要数据坚决不能出境。特别是《中华人民共和国网络安全法》的实施&#xff0c;国内验签SSL证书成为了提升网站安全性、保护用户数据和维护网站信誉的重要工具。 国内验签SSL证书的优势 1数据不出境 根据国家相关法…

基于springboot+mybatis+vue的项目实战之(后端+前后端联调)

步骤&#xff1a; 1、项目准备&#xff1a;创建数据库&#xff08;之前已经创建则忽略&#xff09;&#xff0c;以及数据库连接 2、建立项目结构文件夹 3、编写pojo文件 4、编写mapper文件&#xff0c;并测试sql语句是否正确 5、编写service文件 6、编写controller文件 …

PLC学习笔记

PLC学习笔记 前言一、一些基操知识二、GX works2编程2.1 位逻辑1.2 中间寄存器1.3 PLC的扫描方式 总结 前言 我这个人真的是太渴望知识了~ 一、一些基操知识 一般X表示输入&#xff0c;Y表示输出。一般八个为一组X0~X7M表示中间寄存器&#xff0c;M0~M7时间T、计数C 二、GX …

Java基于Spring Boot框架的课程管理系统(附源码,说明文档)

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

董浩影评

本文来自博客园,作者:↑-↑-我-的-仓-鼠-↑-↑,转载请注明原文链接:https://www.cnblogs.com/donghao99/p/18182035

《视觉十四讲》例程运行记录(5)——运行ch8视觉里程计2光流法和直接法的实践例程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、运行ch8的例程代码1. 编译例程代码前的修改2. 编译例程3. 编译报错(1) 报错一&#xff1a;使用cmake .. 编译时出现(2) 报错二&#xff1a;make编译时出现(3) 报…

Rust | 实现 API 限速操作 Example

在这篇文章中,我们将讨论如何在 Rust 中实现 API 限速。当涉及到生产中的服务时,是为了确保不良行为者不会滥用 API——这就是 API 限速的作用所在。 我们将实现 “滑动窗口” 算法,通过动态周期来检查请求历史,并使用基本的内存 hashmap 来存储用户 IP 及其请求时间。我们…

synchronized关键字的底层原理

1synchronized关键字的底层原理 Monitor 举个例子&#xff1a; 1.线程1执行synchronized代码块&#xff0c;里面用到了lock(对象锁)。首先会让这个lock对象和monitor关联&#xff0c;判断monitor中的owner属性是否为null。如果为null直接获取对象锁。owner只能关联一个线程。 2…

【JUC】并发编程 Synchronized 锁升级原理

Synchronized如何实现同步/互斥的效果&#xff1f; monitorenter&#xff1a; 将锁对象对象头中Mark Word的前30bit替换成指向操作系统中与其关联的monitor对象&#xff0c;将锁记录位状态改为10 monitorexit&#xff1a; 将锁对象对象头中Mark Word进行重置&#xff0c;重新恢…

Tasks 和算子链

Flink中的每一个操作算子称为一个Task(任务),算子的每个具体实例则称为SubTask(子任务),SubTask是Flink中最小的处理单元,多个SubTask可能在不同的机器上执行。一个TaskManager进程包含一个或多个执行线程,用于执行SubTask。 TaskManager中的一个Task Slot对应一个执行…

MT3516W-ASEMI工业电源专用MT3516W

MT3516W-ASEMI工业电源专用MT3516W编辑:ll MT3516W-ASEMI工业电源专用MT3516W 型号:MT3516W 品牌:ASEMI 封装:MTW-5 最大重复峰值反向电压:1600V 最大正向平均整流电流(Vdss):35A 功率(Pd):大功率 芯片个数:5 引脚数量:5 类型:插件整流桥、整流方桥 正向浪涌电流:45…

IP SSL证书申请教程:实现HTTPS加密访问

随着网络安全意识的提高&#xff0c;HTTPS加密访问已经成为网站安全性的重要标准。通过安装SSL证书&#xff0c;网站可以实现数据的加密传输&#xff0c;有效保护用户隐私和数据安全。本文将详细介绍如何为IP地址申请SSL证书&#xff0c;并实现HTTPS加密访问。 一、准备工作 …

会充电的CANoe-赋能新能源汽车,高效完成即插即充(PnC)智能充电功能测试

ISO 15118-2标准中描述的PnC功能,可以实现插枪即充电,识别、计费信息、充电参数都通过高级别通信在EV和EVSE之间自动交换。简化了电动汽车的充电过程,提高了用户体验,为电动汽车行业带来了更智能、更便捷的充电解决方案。然而,电动汽车和充电站之间要实现自动通信和计费,…

数据结构(四)—— 堆和二叉树(上)

制作不易&#xff0c;三连支持一下呗&#xff01;&#xff01;&#xff01; 文章目录 前言一、树的概念及结构二、二叉树的概念及结构总结 前言 这篇博客我们将进行更加复杂的一种数据结构的学习——树形结构。 一、树的概念及结构 树是一种非线性的数据结构&#xff0c;它是…

03 插入排序

03 插入排序1.插入排序的含义类似扑克牌,假设认为0-0位置有序,再把0-1的位置变有序,循环直到所有的有序。每次拿取右侧的数字,一个一个对比放到左侧来。2.示例代码 def insertion_sort(arr):if arr is None or len(arr) < 2:returnfor i in range(1, len(arr)):# 0 ~ i-…

物联网工程毕业后没有一技之长,转行网络安全可行吗?

我21年毕业&#xff0c;大学专业是物联网工程&#xff0c;我相信很多人在象牙塔里都很迷茫&#xff0c;到了大三大四才开始慢慢焦虑自己该从事什么工作培养一技之长&#xff0c;或者是跟随大部队考研继续逃避社会&#xff0c;我选择了后者。21年7月拿到毕业证以后因为没有一技之…

A Bug‘s Life (并查集)

//新生训练 #include <iostream> #include <algorithm> using namespace std; const int N 5000; int p[N], sz[N]; int n, m; int find(int x) {if (p[x] ! x)p[x] find(p[x]);return p[x]; } int main() {int T;scanf("%d", &T);for (int k 1; …

IR2104详解

摘要:从NMOS到半桥驱动 关键词:NMOS、半桥、死区、自举升压目录基础知识 NMOS原理 半桥控制原理 IR2104简介 示例电路 引脚定义 电路原理详解 自举升压 死区控制 总结 链接 引入:IR2104是我上手的第一个半桥栅极驱动芯片,使用两片IR2104就可以搭建一个全桥电路控制电机的正…