C1889 [2019nwu校赛]北境之都(三分法 + 前缀和)

本文介绍了一种使用三分法求解在给定限制条件下调整一系列房屋高度以达到最小总成本的方法。通过预处理数列的排序、前缀和及前缀平方和,实现了高效查找和计算。代码实现采用C++,详细展示了如何通过二分搜索找到满足条件的元素,并利用三分法确定最优解。
摘要由CSDN通过智能技术生成

在这里插入图片描述
我们设当前所有房子中最低的高度是x,那么允许出现的最高高度就是x+m了,于是将所有比x低的高度都修改为x,比x+m高的修改为x+m,处于[x,x+m]的则无需修改.
在这里插入图片描述
展开这个式子,发现是一个开口向上的二次函数,其中X为自变量,其余都是已知,满足先减后增的性质,故可用三分求极值.
这里我们先将B数列排序,再预处理他的前缀和与前缀平方和,那么O(log*log)足够了。(第二个log为每次找比X小的数,比X+M大的数)

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 2e5 + 1;
typedef long long ll;

ll n, m, a[maxn];
ll sum[maxn];		//前缀和
ll mul[maxn];		//前缀平方和

int BinarySearchLeft(int h)		//返回h的左边第一个元素下标
{
	int l = 1, r = n, mid;
	while (l <= r)
	{
		mid = (l + r) >> 1;
		if(h <= a[mid]) r = mid - 1;
		else l = mid + 1;
	}
	return r;
}

int BinarySearchRight(int h)	//返回h的有边第一个元素下标
{
	int l = 1, r = n, mid;
	while (l <= r)
	{
		mid = (l + r) >> 1;
		if(h >= a[mid]) l = mid + 1;
		else r = mid - 1;
	}
	return l;
}

ll f(int h)						//函数f(x)
{
	int l = BinarySearchLeft(h);
	int r = BinarySearchRight(h + m);

	ll tmp = mul[l] + 1LL * h * h * l - 2LL * h * sum[l];
	if(r <= n)
		tmp += mul[n] - mul[r - 1] + 1LL * (h + m) * (h + m) * (n - r + 1) - 2LL * (h + m) * (sum[n] - sum[r - 1]);
	return tmp;
}

ll SanFen(int l, int r)			//三分法算最优解
{
	while (l < r - 1)
	{
		int mid = (l + r) >> 1;
		int midr = (mid + r) >> 1;
		if(f(mid) > f(midr))
			l = mid;
		else
			r = midr;
	}
	return f(l) < f(r) ? f(l) : f(r);
}

int main()
{
	ll ave = 0, ans = 0, minans = 1e18;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		cin >> a[i], ave += a[i];
	sort(a + 1, a + n + 1);
	ave /= n;

	for (int i = 1; i <= n; i++)	//预处理
	{
		sum[i] = sum[i - 1] + a[i];
		mul[i] = mul[i - 1] + a[i] * a[i];
	}

	cout << SanFen(ave - m, ave + m) << endl;

	return 0;
}
内容简介   本书从Windows内核编程出发,全面系统地介绍了串口、键盘、磁盘、文件系统、网络等相关的Windows内核模块的编程技术,以及基于这些技术实现的密码保护、防毒引擎、文件加密、网络嗅探、网络防火墙等信息安全软件的核心组件的具体编程。主要知识重点包括:Windows串口与键盘过滤驱动、Windows虚拟存储设备与存储设备过滤驱动、Windows文件系统过滤驱动、文件系统透明加密/解密驱动、Windows各类网络驱动(包括TDI过滤驱动及三类NDIS驱动),以及最新的WDF驱动开发模型。有助于读者熟悉Windows内核驱动的体系结构,并精通信息安全类的内核编程技术。本书的大部分代码具有广泛的兼容性,适合从Windows 2000 一直到目前最新的Windows 7 Beta 版。   本书适合大专院校计算机系的学生、普通Windows程序员、Windows内核程序员、信息安全行业的程序员,以及希望了解Windows系统底层知识的计算机编程爱好者使用。阅读本书,需要读者有C语言、数据结构、操作系统和计算机网络的基础知识。 目录: 封面 -25 扉页 -24 内容简介 -23 序 -22 关于本书作者和贡献者 -20 前言 -18 阅读注意 -16 目录 -12 正文 1 第1章 内核上机指导 1 1.1 下载和使用WDK 2 1.1.1 下载安装WDK 2 1.1.2 编写第一个C文件 3 1.1.3 编译一个工程 5 1.2 安装与运行 6 1.2.1 下载一个安装工具 6 1.2.2 运行与查看输出信息 7 1.2.3 在虚拟机中运行 9 1.3 调试内核模块 9 1.3.1 下载和安装WinDbg 9 1.3.2 设置Windows XP 调试执行 10 1.3.3 设置Vista调试执行 11 1.3.4 设置VMWare的管道虚拟串口 11 1.3.5 设置Windows内核符号表 13 1.3.6 实战调试first 14 练习题 16 第2章 内核编程环境及其特殊性 17 2.1 内核编程的环境 18 2.1.1 隔离的应用程序 18 2.1.2 共享的内核空间 19 2.1.3 无处不在的内核模块 20 2.2 数据类型 21 2.2.1 基本数据类型 21 2.2.2 返回状态 22 2.2.3 字符串 23 2.3 重要的数据结构 23 2.3.1 驱动对象 23 2.3.2 设备对象 25 2.3.3 请求 26 2.4 函数调用 28 2.4.1 查阅帮助 28 2.4.2 帮助中有的几类函数 30 2.4.3 帮助中没有的函数 32 2.5 Windows的驱动开发模型 32 2.6 WDK编程中的特殊点 33 2.6.1 内核编程的主要调用源 33 2.6.2 函数的多线程安全性 34 2.6.3 代码的中断级 36 2.6.4 WDK中出现的特殊代码 37 练习题 38 第3章 串口的过滤 40 3.1 过滤的概念 41 3.1.1 设备绑定的内核API之一 41 3.1.2 设备绑定的内核API之二 43 3.1.3 生成过滤设备并绑定 43 3.1.4 从名字获得设备对象 45 3.1.5 绑定所有串口 46 3.2 获得实际数据 47 3.2.1 请求的区分 47 3.2.2 请求的结局 48 3.2.3 写请求的数据 49 3.3 完整的代码 50 3.3.1 完整的分发函数 50 3.3.2 如何动态卸载 52 3.3.3 完整的代码 53 本章的示例代码 53 练习题 54 第4章 键盘的过滤 56 4.1 技术原理 57 4.1.1 预备知识 57 4.1.2 Windows中从击键到内核 58 4.1.3 键盘硬件原理 60 4.2 键盘过滤的框架 61 4.2.1 找到所有的键盘设备 61 4.2.2 应用设备扩展 64 4.2.3 键盘过滤模块的DriverEntry 65 4.2.4 键盘过滤模块的动态加载 66 4.3 键盘过滤的请求处理 68 4.3.1 通常的处理 68 4.3.2 PNP的处理 69 4.3.3 读的处理 70 4.3.4 读完成的处理 71 4.4 从请求中打印出按键信息 72 4.4.1 从缓冲区中获得KEYBOARD_INPUT_DATA 72 4.4.2 从KEYBOARD_INPUT_DATA中得到键 73 4.4.3 从MakeCode到实际字符 74 4.5 Hook分发函数 75 4.5.1 获得类驱动对象 76 4.5.2 修改类驱动的分发函数指针 77 4.5.3 类驱动之下的端口驱动 78 4.5.4 端口驱动和驱动之间的协作机制 79 4.5.5 找到关键的回调函数的条件 80 4.5.6 定义常数和数据结构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值