AcWing105. 七夕祭

题目

七夕节因牛郎织女的传说而被扣上了「情人节」的帽子。

于是 TYVJ 今年举办了一次线下七夕祭。

Vani 同学今年成功邀请到了 cl 同学陪他来共度七夕,于是他们决定去 TYVJ 七夕祭游玩。

TYVJ 七夕祭和 11 区的夏祭的形式很像。

矩形的祭典会场由 N N N M M M 列共计 N × M N×M N×M 个摊点组成。

虽然摊点种类繁多,不过 cl 只对其中的一部分摊点感兴趣,比如章鱼烧、苹果糖、棉花糖、射的屋……什么的。

Vani 预先联系了七夕祭的负责人 zhq,希望能够通过恰当地布置会场,使得各行中 cl 感兴趣的摊点数一样多,并且各列中 cl 感兴趣的摊点数也一样多。

不过 zhq 告诉 Vani,摊点已经随意布置完毕了,如果想满足 cl 的要求,唯一的调整方式就是交换两个相邻的摊点。

两个摊点相邻,当且仅当他们处在同一行或者同一列的相邻位置上。

由于 zhq 率领的 TYVJ 开发小组成功地扭曲了空间,每一行或每一列的第一个位置和最后一个位置也算作相邻。

现在 Vani 想知道他的两个要求最多能满足多少个。

在此前提下,至少需要交换多少次摊点。

输入格式

第一行包含三个整数 N N N M M M T T T T T T 表示 cl 对多少个摊点感兴趣。

接下来 T 行,每行两个整数 x , y x,y x,y,表示 cl 对处在第 x x x 行第 y y y 列的摊点感兴趣。

输出格式

首先输出一个字符串。

如果能满足 Vani 的全部两个要求,输出 both

如果通过调整只能使得各行中 cl 感兴趣的摊点数一样多,输出 row

如果只能使各列中 cl 感兴趣的摊点数一样多,输出 column

如果均不能满足,输出 impossible

如果输出的字符串不是 impossible, 接下来输出最小交换次数,与字符串之间用一个空格隔开。

数据范围

  • 1 ≤ N , M ≤ 100000 1≤N,M≤100000 1N,M100000
  • 0 ≤ T ≤ min ⁡ ( N ∗ M , 100000 ) 0≤T≤\min(N∗M,100000) 0Tmin(NM,100000)
  • 1 ≤ x ≤ N 1≤x≤N 1xN
  • 1 ≤ y ≤ M 1≤y≤M 1yM

输入样例

2 3 4
1 3
2 1
2 2
2 3

输出样例

row 1

分析

整体思路

经过分析,可以发现,交换左右两个相邻的摊点只会改变某两列中 cl 感兴趣的摊点数,不会改变每行中 cl 感兴趣的摊点数。同理,交换上下两个相邻的摊点只会改变某两行中 cl 感兴趣的摊点数,不会改变每列中 cl 感兴趣的摊点数。所有可以把本题分成两个互相独立的部分计算。

  1. 通过最少次数的左右交换使每列中 cl 感兴趣的摊点数相同。
  2. 通过最少次数的上下交换使每行中 cl 感兴趣的摊点数相同。

以第 1 个问题为例进行探讨。

可以统计出在初始情况下,每列中 cl 感兴趣的摊点总数,记为 C [ 1 ] C[1] C[1] ~ C [ M ] C[M] C[M]。若 cl 感兴趣的摊点总数 T T T 不能被 M M M 整除,则不可能达到要求。若 T T T 能被 M M M 整除,则目标就是让每列中有 T / M T/M T/M 个 cl 感兴趣的摊点。

思考到这里,可能已经想到了一个与此类似的经典问题 “均分纸牌”。

「均分纸牌」问题

“均分纸牌”问题是说,有 M M M 个人排成一行,他们手中分别有 C [ 1 ] C[1] C[1] ~ C [ M ] C[M] C[M] 张纸牌,在每一步操作中,可以让某个人把自己手中的一张纸牌交给他旁边的一个人,求至少需要多少步操作才能让每个人手中持有的纸牌数相等。显然,当所有人手中持有的纸牌总数 T T T 能被 M M M 整除时,“均分纸牌” 问题有解,在有解时,可以先考虑第一个人。

  1. C [ 1 ] > T / M C[1] > T/M C[1]>T/M,则第一个人需要给第二个人 C [ 1 ] − T / M C[1] - T/M C[1]T/M 张纸牌,即把 C [ 2 ] C[2] C[2] 加上 C [ 1 ] − T / M C[1] - T/M C[1]T/M
  2. C [ 1 ] < T / M C[1] < T/M C[1]<T/M,则第一个人需要从第二个人手中拿 T / M − C [ 1 ] T/M - C[1] T/MC[1] 张纸牌,即把 C [ 2 ] C[2] C[2] 减去 T / M − C [ 1 ] T/M - C[1] T/MC[1]

按照同样的方法,依次考虑第 2 ~ M M M 个人。即使在某个时刻有某个 C [ i ] C[i] C[i] 被减为负数也没有关系,因为接下来 C [ i ] C[i] C[i] 就会从 C [ i + 1 ] C[i+1] C[i+1] 处拿牌,在实际中可以认为 C [ i ] C[i] C[i] C [ i + 1 ] C[i+1] C[i+1] 处拿牌发生在 C [ i − 1 ] C[i-1] C[i1] C [ i ] C[i] C[i] 处拿牌之前。按照这种方法,经过计算,达到目标所需要的最少步数其实就是:
∑ i = 1 M ∣ i ∗ T M − G [ i ] ∣ ,其中 G 是 C 的前缀和,即 G [ i ] = ∑ j = 1 i C [ j ] \sum_{i=1}^M|i * \frac{T}{M} - G[i]|,其中 G 是 C 的前缀和,即 G[i] = \sum_{j = 1}^{i}C[j] i=1MiMTG[i],其中GC的前缀和,即G[i]=j=1iC[j]
其含义是每个 “前缀” 最初共持有 G [ i ] G[i] G[i] 张纸牌,最终会持有 i ∗ T / M i * T/M iT/M 张纸牌,多退少补,会与后边的人发生 “二者之差的绝对值” 张纸牌的交换。

如果设 A [ i ] = C [ i ] − T / M A[i] = C[i] - T/M A[i]=C[i]T/M,即一开始就让每个人手中的纸牌数都减掉 T / M T/M T/M,并且最终让每个人手里都恰好 0 张牌,答案显然不变,就是:
∑ i = 1 M ∣ S [ i ] ∣ ,其中 S 是 A 的前缀和,即 S [ i ] = ∑ j = 1 i A [ j ] \sum_{i=1}^M|S[i]|,其中 S 是 A 的前缀和,即 S[i] = \sum_{j = 1}^i A[j] i=1MS[i],其中SA的前缀和,即S[i]=j=1iA[j]

从数学的角度,以上两个公式也可以互相推导得到。

「环形均分纸牌」问题

回到本题,如果不考虑 “第 1 列与最后一列也是相邻的” 这一条件,那么刚才提到的本题中的第 1 个问题与 “均分纸牌” 问题是等价的。若问题有解,一定存在一种适当的顺序,使得每一步传递纸牌的操作可以转化为交换一对左右相邻的摊点(其中 cl 恰好对这两个摊点之一感兴趣)。

若第 1 列与最后一列相邻,则问题等价于一个 “环形均分纸牌”。仔细思考可以发现,一定存在一种最优解的方案,环上某两个相邻的人之间没有发生纸牌交换操作。于是有一种朴素的做法是,枚举这个没有发生交换的位置,把环断开看成一行,转化为一般的 “均分纸牌” 问题进行计算。

首先,一般的 “均分纸牌” 问题就相当于在第 M M M 个人与第 1 个人之间把环断开,此时这 M M M 个人写成一行,其持有的牌数、前缀和分别是:
A [ 1 ] S [ 1 ] A [ 2 ] S [ 2 ] . . . . . . A [ M ] S [ M ] A[1] \ \ S[1] \\ A[2] \ \ S[2] \\ ... \ \ ... \\ A[M] \ \ S[M] A[1]  S[1]A[2]  S[2]...  ...A[M]  S[M]
如果在第 k k k 个人之后把环断开写成一行,这 M M M 个人持有的纸牌数、前缀和分别是:
A [ k + 1 ] S [ k + 1 ] − S [ k ] A [ k + 2 ] S [ k + 2 ] − S [ k ] . . . . . . A [ M ] S [ M ] − S [ k ] A [ 1 ] S [ 1 ] + S [ M ] − S [ k ] . . . . . . A [ k ] S [ k ] + S [ M ] − S [ k ] A[k + 1] \space\space\space\space\space S[k+1] - S[k] \\ A[k+2] \space\space\space\space\space S[k+2]-S[k] \\ ... \space\space\space\space\space... \\ A[M] \space\space\space\space\space\space\space\space\space\space\space\space\space\space\space S[M] -S[k] \\ A[1] \space\space\space\space\space\space\space\space S[1] + S[M] - S[k] \\ ... \space\space\space\space\space ... \\ A[k] \space\space\space\space\space S[k] + S[M] - S[k] A[k+1]     S[k+1]S[k]A[k+2]     S[k+2]S[k]...     ...A[M]               S[M]S[k]A[1]        S[1]+S[M]S[k]...     ...A[k]     S[k]+S[M]S[k]
注意,此处 A A A 是减去最终每个人手里纸牌数 T / M T/M T/M 之后的数组, A A A 数组均分之后每个人手里都有 0 张纸牌,所以 S [ M ] = 0 S[M] = 0 S[M]=0。也就是说,从第 k k k 个人把环断开写成一行,前缀和数组的变化是每个位置都减去 S [ k ] S[k] S[k]

根据上面推导的公式,所需最小步数为:
∑ i = 1 M ∣ S [ i ] − S [ k ] ∣ ,其中 S 是 A 的前缀和,即 S [ i ] = ∑ j = 1 i A [ j ] \sum_{i = 1}^M |S[i] - S[k]|,其中 S 是 A 的前缀和,即 S[i] = \sum_{j = 1}^iA[j] i=1MS[i]S[k],其中SA的前缀和,即S[i]=j=1iA[j]

k k k 取何值时上式最小?这就是 “AcWing104.货仓选址” 问题!其中 S [ i ] S[i] S[i] 是数轴上 M M M 家商店的位置, S [ k ] S[k] S[k] 是货仓的位置, ∣ S [ i ] − S [ k ] ∣ |S[i] - S[k]| S[i]S[k] 就是二者之间的距离。根本不需要枚举 k k k,只需要把 S S S 从小到大排序,取中位数作为 S [ k ] S[k] S[k] 就是最优解!至此,本题得到完美解决,时间复杂度为 O ( N l o g N + M l o g N ) O(N logN + MlogN) O(NlogN+MlogN)

思路总结

综上所述,本题可类比为行、列方向上的两次 “环形均分纸牌” 问题。环形均分纸牌又类比为 “均分纸牌” 与 “货仓选址” 问题。其中的每一步都仅使用了基本算法和性质,最后转化为了简单而经典的问题。

代码

#include <iostream>
#include <algorithm>
using namespace std;#define ll long long
const int N = 1e5 + 10;int n, m, t, a[N], b[N]; //a数组记录每行感兴趣的摊点个数,b数组记录每列感兴趣的摊点个数
ll s[N]; //前缀和数组int func(int *arr, int x) {ll sum = 0;int avg = t / x; //每行/列应该多少个摊点for (int i = 1; i <= x; i++) arr[i] -= avg; //每行/列减去平均的摊点个数s[0] = 0;for (int i = 1; i <= x; i++) s[i] = s[i - 1] + arr[i];//求前缀和sort(s + 1, s + 1 + x); //排序for (int i = 1; i <= x; i++) sum += abs(s[i] - s[(x + 1) / 2]); //s[(x + 1) / 2]为中位数return sum;
}int main() {cin >> n >> m >> t;int x, y;for (int i = 1; i <= t; i++) {cin >> x >> y;a[x]++;b[y]++;}bool row = !(t % n),  col = !(t % m);if (row && col) {cout << "both ";} else if(row) {cout << "row ";} else if (col) {cout << "column ";} else {cout << "impossible" << endl;return 0;}ll ans = 0;if (row) {ans += func(a, n);} if (col) {ans += func(b, m);}cout << ans << endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/174825.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《C++ 新经典》设计模式前言

文章目录 本章内容概述一、概念二、模式分类本章总结 本章内容概述 本系列将详细剖析王建伟老师编著的 《C 新经典 设计模式》一书&#xff0c;结合书中知识与笔者个人分析&#xff0c;对设计模式进行详细讲解&#xff0c;希望对初学者能够有所帮助。本文将作为此系列的引言&a…

基于halo框架采用docker-compose快速部署个人博客

halo快速部署个人博客 技术方案 dockerdocker-composenginxmysql halo简介 Halo是一款现代化的开源博客/CMS系统&#xff0c;所有代码开源在GitHub上且处于积极维护状态。它是基于 Java Spring Boot 构建的&#xff0c;易于部署&#xff0c;支持REST API、模板系统、附件系…

关于微服务的思考

目录 什么是微服务 定义 特点 利弊 引入时机 需要哪些治理环节 从单体架构到微服务架构的演进 单体架构 集群和垂直化 SOA 微服务架构 如何实现微服务架构 服务拆分 主流微服务解决方案 基础设施 下一代微服务架构Service Mesh 什么是Service Mesh&#xff1f…

vue3 element-plus el-table表头冻结,表头吸顶

一.使用方式 在main.ts页面创建 vue指令 import { createSticky } from /utils/stickyconst app createApp(App)createSticky(app)...app.mount(#app);在el-table标签上使用 v-sticky <div class"table-box"><!--此处的 .table-box 是会出现滚动条的DOM元…

java线程三种方式

1.继承Thread类 线程1.2交替执行 public class MyThread extends Thread {Overridepublic void run() {for (int i 0; i < 100; i) {System.out.println(getName()"------""HelloWorld");}} } /*** desc 继承Thread类&#xff0c;线程1 2 交替执行* …

python实现自动刷平台学时

背景 前一阵子有个朋友让我帮给小忙&#xff0c;因为他每学期都要看视频刷学时&#xff0c;一门平均需要刷500分钟&#xff0c;一学期有3-4门需要刷的。 如果是手动刷的话&#xff0c;比较麻烦&#xff0c;能否帮他做成自动化的。搞成功的话请我吃饭。为了这顿饭&#xff0c;咱…

京东秒杀之商品展示

1 在gitee上添加.yml文件 1.1 添加good-server.yml文件 server:port: 8084 spring:datasource:url: jdbc:mysql://localhost:3306/shop_goods?serverTimezoneGMT%2B8driverClassName: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourceusername: rootpa…

SQL 查询优化的 10 个案例!

在应用开发的早期&#xff0c;数据量少&#xff0c;开发人员开发功能时更重视功能上的实现&#xff0c;随着生产数据的增长&#xff0c;很多SQL语句开始暴露出性能问题&#xff0c;对生产的影响也越来越大&#xff0c;有时可能这些有问题的SQL就是整个系统性能的瓶颈。 SQL优化…

多功能音乐沙漏的设计与实现

【摘要】随着当今社会快节奏生活的发展&#xff0c;当代大学生越来忽视时间管理的重要性&#xff0c;在原本计划只看几个视频只玩几个游戏的碎片化娱乐中耗费了大量的时光&#xff0c;对于自己原本的学习生活产生了巨大的影响。为更加有效的反映时间的流逝&#xff0c;特设计该…

智慧公厕客流统计,是通过什么原理实现的?

在这个信息爆炸的时代&#xff0c;科技已经深刻地渗透到我们生活的方方面面&#xff0c;就连那些看似与现代社会脱节的公厕&#xff0c;也迎来了智慧时代的冲击。智慧公厕客流统计系统的崭新面貌&#xff0c;不仅实现了对卫生间使用情况的精准监测&#xff0c;更为城市管理者提…

第十七章 解读PyTorch断点训练(工具)

主要有以下几方面的内容&#xff1a; 对于多步长训练需要保存lr_schedule初始化随机数种子保存每一代最好的结果 简单详细介绍 最近在尝试用CIFAR10训练分类问题的时候&#xff0c;由于数据集体量比较大&#xff0c;训练的过程中时间比较长&#xff0c;有时候想给停下来&…

Gitee上传代码教程

1. 本地安装git 官网下载太慢&#xff0c;我们也可以使用淘宝镜像下载&#xff1a;CNPM Binaries Mirror 安装成功以后电脑会有Git Bush标识&#xff0c;空白处右键也可查看。 2. 注册gitee账号&#xff08;略&#xff09; 3. 创建远程仓库 4. 上传代码 4.1 在项目文件目录…

go当中的channel 无缓冲channel和缓冲channel的适用场景、结合select的使用

Channel Go channel就像Go并发模型中的“胶水”&#xff0c;它将诸多并发执行单元连接起来&#xff0c;或者正是因为有channel的存在&#xff0c;Go并发模型才能迸发出强大的表达能力。 无缓冲channel 无缓冲channel兼具通信和同步特性&#xff0c;在并发程序中应用颇为广泛。…

坚鹏:贵州银行西南财经大学零售业务数字化转型与场景营销策略

中国银保监会2022年1月正式发布了中国银保监会发布《关于银行业保险业数字化转型的指导意见》&#xff0c;这标准着中国银行业从局部的数字化转型向全面的数字化转型转变&#xff0c;进一步加速了银行数字化转型高潮的到来。 《关于银行业保险业数字化转型的指导意见》提出明确…

【教学类-06-12】20231126 (二)三位数 如何让加减乘除题目从小到大排序(以0-110之间加法为例,做正序排列用)

结果展示 背景需求&#xff1a; 二位数&#xff1a;去0 三位数&#xff08;需要排除很多0&#xff09; 解决思路 一、把数字改成三位数 二、对数组内的题目&#xff0c;8种可能性进行去“0”处理 1、十位数&#xff08;去百位数0&#xff09;十位数&#xff08;去百位数0&am…

淘宝商品详情数据API接口php java python

在当今竞争激烈的电子商务环境中&#xff0c;如何提高用户体验、提升运营效率并保障交易安全性是每个电商平台都需要关注的问题。淘宝作为中国最大的综合性电商平台&#xff0c;一直在不断创新和完善自身的服务体系。其中&#xff0c;淘宝商品详情API接口在跨境系统中发挥着越来…

【C/PTA】指针专项练习(一)

本文结合PTA专项练习带领读者掌握指针&#xff0c;刷题为主注释为辅&#xff0c;在代码中理解思路&#xff0c;其它不做过多叙述。 目录 6-1 删除字符串中数字字符6-2 找最大值及其下标6-3 求两数平方根之和6-4 求一组数中的最大值、最小值和平均值6-5 两个4位正整数的后两位互…

HuggingFace学习笔记--Tokenizer的使用

1--AutoTokenizer的使用 官方文档 AutoTokenizer() 常用于分词&#xff0c;其可调用现成的模型来对输入句子进行分词。 1-1--简单Demo 测试代码&#xff1a; # 分词器测试Demo from transformers import AutoTokenizerif __name__ "__main__":checkpoint "…

数据增强让模型更健壮

在做一些图像分类训练任务时,我们经常会遇到一个很尴尬的情况,那就是: 明明训练数据集中有很多可爱猫咪的照片,但是当我们给训练好的模型输入一张戴着头盔的猫咪进行测试时,模型就不认识了,或者说识别精度很低。 很明显,模型的泛化能力太差,难道戴着头盔的猫咪就不是猫…

线性分类器--数据处理

数据集划分 通常按照 70%&#xff0c;20% &#xff0c;10% 来分数据集 数据处理 斯坦福的线性分类器体验 http://vision.stanford.edu/teaching/cs231n-demos/linear-classify/