D2. Red-Blue Operations (Hard Version)(思维/贪心/前缀和)

news2024/12/24 8:27:34

建议先从easy version开始做。
easy version题解

题目

题意

给定长度为n(1<=n<=200000)的数组
1<=a[i]<=10^9
q个查询(1<=q<=200000),每次查询,给定整数k(1<=k<=10^9)

初始时,每个元素状态都是红色。
对于第i次操作,每次选择从数组中选择一个元素进行操作。

  • 如果当前元素状态为红色,则将该元素的值+i,并变更当前元素状态为蓝色。
  • 如果当前元素状态为蓝色,则将该元素的值-i,并变更当前元素状态为红色。

问,经过k次操作后。得到的新数组,它的元素最小值min,最大能取多大。即求数组的最大 最小值。

思路

当k<=n时,我们贪心地把每个操作,应用到最小的k个元素,即可满足。

当k>n时,复用贪心思路。这里先假设n-k是偶数。

我们把前n大的元素,累加,应用到这n个元素。
怎么确保到最后n次操作时,每个元素的状态刚好是红色(即对应新增状态)呢?我们只要保证,在最后n次操作之前,每个元素都应用了偶数次即可。

为了确保在应用最后n次操作的时候,元素之间的变更最少(这里需要理解下,因为我们要求的是数组的最小值,因此,需要确保整体增加的时候,是相对均匀的)。
我们可以把前面k-n次操作,拆分成(+1,-2),(+3,-4)…这样的成对操作,每个操作都只-1。

设a’为应用了最后n次操作的新数组。设num为剩余的-1操作。
令res = a’[i]-min(a’)。那么这res可以抵消掉数组的-1操作,且不会变更数组最小值。

经过res次-1操作后,数组a’则变成所有元素都相等了,那么之后,每n次-1,我们的数组最小值都会-1。(这里注意向上取整)

优化

利用上述思路,我们可以做到用O(qnlogn)解决问题。但hard version的n,q为200000,显然会TLE。考虑优化。

第一步,查询前预处理,将a数组进行排序处理。

对于k<=n的场景,我们需要更新a[i],并从更新后的a数组获取最小值。

a[i] = a[i] - i + k, 0 <= i < k.

观察到,更新时,a[i]-i的值是与k无关的,我们可以预处理,计算关于a[i]-i的前缀最小值。那么每次查询,我们只需用O(1)的时间就可以快速得到最小值。

下面考虑k>n的场景。
考虑n和k奇偶性相同的场景(奇偶性不同的场景类似)
同样的,对于最小值的计算,我们可以抽取出a[i]-i去做预处理。

for (int i = 0; i < n; ++i) {
	a[i] = a[i] - i + k;
}

对于数组a’更新后,每个元素超出当前最小值的部分,我们也可以做预处理。我们只需计算出它们的总和,减去n个当前最小值min,即为超出部分。
预处理后,每次计算,可以用O(1)的时间。
注意用long long储存。

long long res = sum(a[i]) + (k + (k-n+1))*n/2 - n*cur_min;

详见代码。

代码

#include<string>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 2000000009
//#define inf 0x3f3f3f3f // 这个数太小了,,被坑了 
const int maxn = 200010;

ll n, q, k;
ll a[maxn], pre[maxn]; // pre[j] = min(a[j]-j),0<=j<=i
ll suf[maxn]; // suf[i] = min(a[j]), i<=j<n
ll sum;
void init() {
	pre[0] = a[0] - 0;
	for (int i = 1; i < n; ++i) {
		pre[i] = min(pre[i-1], a[i] - i);
	}
	suf[n] = inf;
	for (int i = n - 1; i >= 0; --i) {
		suf[i] = min(a[i], suf[i+1]);
	}
	sum = 0;
	for (int i = 0; i < n; ++i) {
		sum += a[i];
	}
}
int cal() {
	scanf("%lld", &k);
	/*
	if (n == 1000 && q == 999 && a[0] == 1000000000) { // debug
		printf("k:%d\n", k);
		bool flag = 1;
		for (int i = 0; i < n; ++i) {
			if (a[i] != 1000000000) {
				printf("a[%d]:%d\n", i, a[i]);
				flag = 0;
				break;
			}
		}
		if (flag) {
			printf("all 1000000000 for a\n");
		}
		return 0;
	}
	*/
//	k = 1000000000; // debug
	if (k <= n) { // add [k,...,1] to minist topk elems.
		return min(pre[k-1] + k, suf[k]);
	}
	
	ll num = k - (n - 1); // 用于统计操作数剩余量 
	ll mn; // 最小值 
	ll left = 0; // 每个元素超出当前最小值的部分 的总和 
	if ((k - n) % 2 == 0) { // n 和 k 奇偶性相同 
		--num;
		mn = min(pre[n-1] + k, suf[n]); 
		left = sum + 1LL * (k + (k - n + 1)) * n / 2 - 1LL * n * mn; // 防爆long long 
	} else {
		if (n == 1) { // specail judge
			mn = suf[n-1];
		} else {
			mn = min(pre[n-2] + k, suf[n-1]);	
		}
		left = sum + 1LL * (k + (k - n + 2)) * (n - 1) / 2 - 1LL * n * mn; // 防爆long long 
	}

	num /= 2; // (increase,decrease)的对数 
	num = max(0LL, num - left);
	num = (num + n - 1) / n; // mininum 需要 -1 的次数 ,需要向上取整 
	
//	printf("mn:%d num:%d\n", mn, num); // debug
	return mn - num;
}
void solve() {
	scanf("%lld%lld", &n, &q);
	for (int i = 0; i < n; ++i) {
		scanf("%lld", &a[i]);
	}
	sort(a, a + n);
	init();
	while (q--) {
		printf("%d%c", cal(), !q ? '\n' : ' ');
	}
} 
void debug() {
	n = 1000;
	q = 1000;
	for (int i = 0; i < n; ++i) {
		a[i] = 1000000000;
	}
	init();
	printf("%d\n", cal());
}
int main() {
	int t = 1;
//	scanf("%d", &t);
	while (t--) {
//		debug();
		solve();
	}
}
/*

*/

欢迎关注同名公众号

对方正在debug

今日份 听取wa声一片
那些杀不死你的,终将使你更加强大(暴风哭泣
在这里插入图片描述

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

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

相关文章

【小沐学Unity3d】Unity插件之天气系统UniStorm

文章目录 1、简介1.1 描述1.2 兼容性1.3 价格1.4 特点1.5 示例 3、安装3.1 新建Unity项目3.2 安装插件UniStorm3.3 介绍UniStorm工具栏3.4 入门使用 4、脚本开发4.1 接口简介4.1.1 天气4.1.2 时间4.1.3 程度4.1.4 季节4.1.5 系统4.1.6 其他 4.2 接口测试4.2.1 测试1 结语 1、简…

教你如何使用Nodejs搭建HTTP web服务器并发布上线公网

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 转载自内网穿透工具的文章&#xff1a;使用Nodejs搭建HTTP服务&#xff0c;并实现公网远程访问「内网穿透」 前言 Node.js…

60岁的机器视觉工程师,你还在敲代码?不想做机器视觉工程师,还可以做什么?机器视觉工程师职业生命线有多长​?

如果按程序员参加工作时间为22岁计算,平均退役年龄为35岁计算的话,程序员的职业寿命大概为14年。为什么程序员的职业生命线如此短暂呢?大致有以下几点—— 1、编程技术层出不穷,迭代速度非常快,这时候就需要我们不断的学习,不断地保持学习能力,当随着年龄的增长我们的学…

【数据结构】链表:带头双向循环链表的增删查改

本篇要分享的内容是带头双向链表&#xff0c;以下为本片目录 目录 一、链表的所有结构 二、带头双向链表 2.1尾部插入 2.2哨兵位的初始化 2.3头部插入 2.4 打印链表 2.5尾部删除 2.6头部删除 2.7查找结点 2.8任意位置插入 2.9任意位置删除 在刚开始接触链表的时候&…

86. print输出函数知识拓展(有练习题)

86. print输出函数知识拓展&#xff08;有练习题&#xff09; 文章目录 86. print输出函数知识拓展&#xff08;有练习题&#xff09;1. print函数语法2. 横着输出数字序列3. 竖着输出数字序列4. 循环输出5. 总结 1. print函数语法 print[prɪnt]&#xff1a;打印&#xff0c;…

少儿编程scratch -- 基础篇

1.开篇 花费40分钟 首先&#xff0c;我们学的是scratch(划痕&#xff09;&#xff0c;Scratch 是麻省理工学院的“终身幼儿园团队”在 2007 年 [5] 发布的一种图形化编程工具&#xff0c;主要面对全球青少年开放&#xff0c;是图形化编程工具当中最广为人知的一种&…

ShardingSphere-JDBC整合SpringBoot JPA读写分离失败

问题 最近在整合ShardingSphere JDBC和Spring Boot的时候遇到一个问题,当ORM框架使用JPA时,读写分离会失效,查询仍然走主库并不会走从库!同样的配置使用Mybatis就没有任何问题。 在查阅各种资料后,初步确定未JPA事务问题 ShardingSphere负载均衡算法 我当前使用的版本是…

FIDO认证 无密码的愿景

目录 1、简介 2、关于FIDO联盟 3、FIDO如何工作 3.1 FIDO 注册 3.2 FIDO登录 4、FIDO2 4.1 W3C WebAuthn 4.2 CTAP2 4.3 CTAP1 4.4 FIDO UAF 4.5 FIDO U2F 5、FIDO身份验证的优势 5.1 安全 5.2 便利性 5.3 隐私政策 5.4 可扩展性 1、简介 FIDO&#xff08;在线…

Python 爬虫(一):爬虫伪装

1 简介 对于一些有一定规模或盈利性质比较强的网站&#xff0c;几乎都会做一些防爬措施&#xff0c;防爬措施一般来说有两种&#xff1a;一种是做身份验证&#xff0c;直接把虫子挡在了门口&#xff0c;另一种是在网站设置各种反爬机制&#xff0c;让虫子知难而返。 2 伪装策…

【2023 · CANN训练营第一季】初识新一代开发者套件 Atlas 200I DK A2 第二章——安装Atlas 200I DK A2跑通第一个案例

准备相关软件 包括一台PC机&#xff08;空间大于10g)&#xff0c;读卡器&#xff0c;32gsd卡&#xff0c;一根网线。 具体步骤&#xff1a; 开始烧录开发板镜像&#xff1a;将sd卡插入读卡器&#xff0c;将读卡器插入PC机的USB接口&#xff0c;根据相关链接在PC机下载制卡工具…

混合云到底是什么?

大型企业不能再仅仅拥有本地系统就可以逃脱&#xff1b;因此&#xff0c;将一些数字化运营迁移到云端成为了必要。 第一步涉及选择是使用公共云还是私有云&#xff0c;或者两者都使用。使用两者是混合云。 但混合云到底是什么&#xff1f;在回答之前&#xff0c;让我们看看这…

图生图—AI图片生成Stable Diffusion参数及使用方式详细介绍

本文为博主原创文章&#xff0c;未经博主允许不得转载。 本文为专栏《Python从零开始进行AIGC大模型训练与推理》系列文章&#xff0c;地址为“https://blog.csdn.net/suiyingy/article/details/130169592”。 Stable Diffusion webui的详细安装步骤以及文生图&#xff08;txt2…

【Linux】Linux入门学习之常用命令四

介绍 这里是小编成长之路的历程&#xff0c;也是小编的学习之路。希望和各位大佬们一起成长&#xff01; 以下为小编最喜欢的两句话&#xff1a; 要有最朴素的生活和最遥远的梦想&#xff0c;即使明天天寒地冻&#xff0c;山高水远&#xff0c;路远马亡。 一个人为什么要努力&a…

Jenkins教程-Docker安装Jenkins,并构建任务等

本文主要介绍如何在docker中安装Jenkins&#xff0c;启动容器后&#xff0c;如何使用Jenkins构建自己的项目&#xff0c;创建任务等 文章目录 前言Docker安装Jenkins访问Jenkins并配置Jenkins构建项目创建任务源码管理构建触发器BuildPost Steps 设置手工触发构建 前言 参考链…

Redis集群安全加固

本博客地址&#xff1a;https://security.blog.csdn.net/article/details/130692909 一、为Redis启用密码验证 默认情况下&#xff0c;Redis不执行任何密码身份验证。能够通过IP端口连接Redis的客户端均可以直接访问Redis中的数据。在启动Redis服务时&#xff0c;通过设置req…

玩转自动化操作神器n8n之(1)n8n的简介与安装

文章目录 1. 简介 2. 安装2.1. 使用npx进行安装2.2. 使用docker进行安装 2.3. 设置端口&#xff08;可选&#xff09; 3. 登录4. 搜索工作流 1. 简介 n8n是一款强大的工作流程自动化工具&#xff0c;可以自定义想要使用的功能和应用程序。n8n基于节点能够将任何工具连接在一起…

使用插件快速生成代码

使用插件快速生成代码 咋们常说&#xff0c;授人以鱼不如授人以渔&#xff0c;在这里给大家提供一些技巧性的东西&#xff0c;方便一些新手同学可以快速上手&#xff0c;同时&#xff0c;也提高我们的开发兴趣与开发热情&#xff01; 主要讲什么呢&#xff0c;我们来学一学如何…

低代码信创开发核心技术(二):手撕灵活好用的Vue拖拉拽布局系统

前言 随着信息化时代的到来&#xff0c;软件已经成为企业和个人不可或缺的工具。然而&#xff0c;许多人在开发软件时遇到了各种问题&#xff0c;比如开发周期长、技术门槛高、成本高昂等等。为了解决这些问题&#xff0c;低代码平台应运而生。低代码平台是一种快速开发工具&a…

Golang每日一练(leetDay0067) 第十行、打家劫舍I

目录 195. 第十行 Tenth Line &#x1f31f; 198. 打家劫舍 I House Robber &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 195. 第十行 Tenth Line 给定一…

PySide6/PyQT多线程之 异常情况和优先级指南

前言 在PySide6/PyQT 中使用多线程时&#xff0c;线程的优先级和异常情况处理同样是重要的概念。 本文纯理论知识&#xff0c;无实操。换句话说&#xff0c;就是水文~~ 尽管在一般情况下我们不需要过多关注线程的优先级&#xff0c;但了解它的概念对于特定场景下的多线程编程仍…