刷题记录:牛客NC51112Stars in Your Window 扫描线

news2024/11/17 5:55:02

传送门:牛客

题目描述:

Here comes the problem: Assume the sky is a flat plane. All the stars lie on it with a location (x, y). for each 
star, there is a grade ranging from 1 to 100, representing its brightness, where 100 is the brightest and 1 is the 
weakest. The window is a rectangle whose edges are parallel to the x-axis or y-axis. Your task is to tell where I 
should put the window in order to maximize the sum of the brightness of the stars within the window. Note, the 
stars which are right on the edge of the window does not count. The window can be translated but rotation is 
not allowed. 
输入:
3 5 4
1 2 3
2 3 2
6 3 1
3 5 4
1 2 3
2 3 2
5 3 1
输出:
5
6

一道有关扫描线的题目.假设你扫描线算法并不会,那么可以去学一下扫描的算法再来做这道题关于扫描线算法,网上有大量博客对此进行讲解,此处就不在赘述了.

关于这道题,绝大部分题解对于矩形的建立都是一笔带过,并且往往都是将星星当做矩形的左下顶点,这样做的原因却几乎没有一个详细的解释,读者难免感到无法读懂.

对于一颗星星,此时我们想一下假设一个 w ∗ h w*h wh的矩形能够罩住他,此时考虑一下都是什么情况,我们考虑一下极限情况,我们会发现是一下这种情况(中间为星星):
在这里插入图片描述
也就是从右上角开始的黑色矩形最远平移到红色矩形的位置,最下平移到黄色矩形的位置.那么此时我们会发现对于一颗星星和一个矩形来说,只要这个矩形的右上角在我们的黑色矩形位置,此时形成的矩形肯定就能包裹住我们的星星,但是注意此时我们的题面中说在矩形的边框上的星星是不满足的.又因为两个题面上说坐标和矩形长宽都是整数,这个意味着两个星星的横坐标距离大于等于1.所以此时我们可以将矩形的长宽缩小1,[想一下,对于左右两个星星来说,假设他们距离x,那么此时我们的矩形的长必然是要大于才行,又因为是整数,所以此时长至少为x+1.所以此时我们选择将长缩小1,这样的话对于我们删减后的矩形来说,星星在边框上时合法的,就变得易于操作了.]

那么对于所有的星星来说,我们都以这个星星作为我们的新矩形的左下顶点来建立矩形,以亮度作为矩形的贡献.通过我们之前的分析可以发现,我们最终的贡献其实就是矩形重叠的亮度的最大值.此时我们可以使用扫描线的思想来做这道题,以矩形上下边为扫描线,下边权为正,上边权为负开始从下往上扫并且维护区间最大值即可.

注意点:在扫描线从下往上扫的过程中遇到y值相同的扫描线应采取先减再加的原则(在牛客上因为数据比较弱并没有卡这个点,很多人可能都注意不到)

优化&巧妙的想法:对于这种只需要区间[1,n]的维护值来说,我们建立线段树的时候可以不使用pushdown(因为我们根本不需要关注子节点是怎么样的),在子节点pushup的时候将父节点对子节点的lazy加上即可.
注意,此方法在我看来并不具有很强的意义,虽然省去了对子节点的维护,码量减少了,但是因为这种方式大大的修改了模板,会导致出现一写奇奇怪怪的错误甚至思维上的混乱,但是在平时可以挑战一下,这样改变常规的做法可以大大增强自己对线段树的理解

下面是具体的代码部分(标准版维护版):

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define int long long
#define maxn 1000000
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
struct Segment_tree{
	int l,r,mx,lazy;
}tree[maxn*4];
int n,w,h;
struct Line{
	int l,r,y,cate;
	bool operator < (const Line &rhs) const {
		if(y==rhs.y) return cate<rhs.cate;
		else return y<rhs.y;
	}
}line[maxn];
vector<int>v;
int Get_id(int x) {
	return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void build(int l,int r,int rt) {
	tree[rt].l=l;tree[rt].r=r;
	if(l==r) return ;
	int mid=(l+r)>>1;
	build(lson);build(rson);
}
void pushup(int rt) {
	tree[rt].mx=max(tree[ls].mx,tree[rs].mx);
}
void change(int rt,int val) {
	tree[rt].mx+=val;tree[rt].lazy+=val;
}
void pushdown(int rt) {
	change(ls,tree[rt].lazy);change(rs,tree[rt].lazy);
	tree[rt].lazy=0;
}
void update(int l,int r,int val,int rt) {
	if(tree[rt].l==l&&tree[rt].r==r) {
		change(rt,val);
		return ;
	}
	if(tree[rt].lazy) pushdown(rt);
	int mid=(tree[rt].l+tree[rt].r)>>1;
	if(r<=mid) update(l,r,val,ls);
	else if(l>mid) update(l,r,val,rs);
	else update(l,mid,val,ls),update(mid+1,r,val,rs);
	pushup(rt);
}
signed main() {
	while(scanf("%lld%lld%lld",&n,&w,&h)!=EOF) {
		v.clear();int cnt=0;
		for(int i=1;i<=n;i++) {
			int x=read(),y=read(),val=read();
			line[++cnt].l=x;line[cnt].r=x+w;
			line[cnt].y=y;line[cnt].cate=val;
			line[++cnt].l=x;line[cnt].r=x+w;
			line[cnt].y=y+h;line[cnt].cate=-val;
			v.push_back(x);v.push_back(x+w);
		}
		sort(line+1,line+2*n+1);
		sort(v.begin(),v.end());
		v.erase(unique(v.begin(),v.end()),v.end());
		int Size=v.size();
		build(1,Size,1);
		int ans=-ll_INF;
		for(int i=1;i<=2*n;i++) {
			int x=Get_id(line[i].l),x2=Get_id(line[i].r);
			update(x,x2-1,line[i].cate,1);
			ans=max(ans,tree[1].mx);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

下面是具体的代码部分(省略 p u s h d o w n pushdown pushdown版):

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
#define int long long
#define maxn 1000010
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
struct Segment_tree{
	int l,r,mx,lazy;
}tree[maxn*4];
int n,w,h;
struct Line{
	int l,r,y,cate;
	bool operator < (const Line &rhs) const {
		if(y==rhs.y) return cate<rhs.cate;
		else return y<rhs.y;
	}
}line[maxn];
vector<int>v;
int Get_id(int x) {
	return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void build(int l,int r,int rt) {
	tree[rt].l=l;tree[rt].r=r;tree[rt].mx=0;tree[rt].lazy=0;
	if(l==r) return ;
	int mid=(l+r)>>1;
	build(lson);build(rson);
}
void pushup(int rt) {
	tree[rt].mx=max(tree[ls].mx+tree[rt].lazy,tree[rs].mx+tree[rt].lazy);
}
void update(int l,int r,int val,int rt) {
	if(tree[rt].l==l&&tree[rt].r==r) {
		tree[rt].mx+=val;tree[rt].lazy+=val;
		return ;
	}
	int mid=(tree[rt].l+tree[rt].r)>>1;
	if(r<=mid) update(l,r,val,ls);
	else if(l>mid) update(l,r,val,rs);
	else update(l,mid,val,ls),update(mid+1,r,val,rs);
	pushup(rt);
}
signed main() {
	while(scanf("%lld%lld%lld",&n,&w,&h)!=EOF) {
		v.clear();int cnt=0;
		for(int i=1;i<=n;i++) {
			int x=read(),y=read(),val=read();
			line[++cnt].l=x;line[cnt].r=x+w;
			line[cnt].y=y;line[cnt].cate=val;
			line[++cnt].l=x;line[cnt].r=x+w;
			line[cnt].y=y+h;line[cnt].cate=-val;
			v.push_back(x);v.push_back(x+w);
		}
		sort(line+1,line+2*n+1);
		sort(v.begin(),v.end());
		v.erase(unique(v.begin(),v.end()),v.end());
		int Size=v.size();
		build(1,Size,1);
		int ans=-ll_INF;
		for(int i=1;i<=2*n;i++) {
			int x=Get_id(line[i].l),x2=Get_id(line[i].r);
			update(x,x2-1,line[i].cate,1);
			ans=max(ans,tree[1].mx);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

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

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

相关文章

数据库大量数据导出导入的操作

基于上一篇文章&#xff0c;我想到如果在数据库之间拥有大量数据的表数据的导入导出&#xff0c;该如何快速完成表的导入导出工作呢&#xff1f; 思路一:使用db软件工具导出数据&#xff0c;然后向新数据库导入数据。我用的是dbserver22.3.4&#xff0c;不出意外的是&#xff0…

【读书笔记】《深入浅出数据分析》第二章 检验你的理论

文章目录一&#xff0c;相关分析方法1&#xff0c;相关系数二&#xff0c;相关性不等于因果关系三&#xff0c;证明因果关系&#xff0c;“控制变量法”?本章主要说明了两个问题&#xff1a; 1&#xff0c;相关性不等于因果关系 2&#xff0c;如何判断两种数据之间是相关性&am…

深圳/东莞/惠州师资比较强的CPDA数据分析认证

深圳/东莞/惠州师资比较强的CPDA数据分析认证培训机构 CPDA数据分析师认证是中国大数据领域有一定权威度的中高端人才认证&#xff0c;它不仅是中国较早大数据专业技术人才认证、更是中国大数据时代先行者&#xff0c;具有广泛的社会认知度和权威性。 无论是地方政府引进人才、…

Android 高性能列表:RecyclerView + DiffUtil

文章目录背景介绍一般刷新 notifyDataSetChanged()局部刷新实现调用代码准备工作创建 MyDiffUtilCallback 类继承 DiffUtil.Callback 抽象类MyAdpter 类代码实现步骤总结通过 log 证实 diffutil 的局部刷新diffutil 优化后台线程参考主线程参考diff 更新优化后写法相关参考背景…

Spring的一些知识点

什么是Spring&#xff1f; Spring是一种轻量级的开发框架&#xff0c;旨在提高开发人员的开发效率以及系统的可维护性。 Spring的核心模块 Spring Core是基础模块&#xff0c;可以说Spring的其他功能都要依赖于该类库&#xff0c;主要提供IOC的依赖注入功能&#xff1b; Spri…

动手学深度学习v2—01数据操作+数据预处理

此次用到的虚拟环境&#xff1a;pytorchmwy项目名称&#xff1a;limuAI所需框架和工具&#xff1a;pytorch&#xff0c;pandas一、创建CSV文件所需工具&#xff1a;pandas在与项目同等目录下创建一个文件夹名为data&#xff0c;其中文件名称为house_tiny.csv。代码如下&#xf…

Java基础:拼图小游戏

涉及到的知识: 1.图形用户接口GUI(Graphical User Interface)用图形化的方式显示操作界面 两个体系: AWT包和Swing包 2.界面会用到JFrame类 3.界面中的菜单会用到JMenuBar, JMenu, JMenuItem 4.添加图片 在设置完JLabel的location之后还需要获得展示内容的窗体, 通过setLay…

吃鸡用什么蓝牙耳机效果好?手游吃鸡公认最好的几款蓝牙耳机

蓝牙耳机的作用很多&#xff0c;几乎每个人都需要一副很棒的耳机在通勤或锻炼途中使用&#xff0c;并且玩游戏也少不了它&#xff0c;手游近几年十分的流行&#xff0c;下面整理了几款性能不错的蓝牙耳机。 第一款&#xff1a;南卡小音舱蓝牙耳机 蓝牙版本&#xff1a;5.3 发…

【Linux】如何将ntfs硬盘挂载到home目录下并具有读写权限

步骤1. 查看当前挂载的硬盘及其挂载点2. 查看需要挂载到home下的磁盘类型信息3. 在home下新建一个空的文件夹作为该磁盘的新挂载点4. 以ntfs类型的硬盘为例&#xff0c;使用mount命令进行挂载5. 问题1&#xff1a;进程占用了磁盘6. 问题2&#xff1a;磁盘权限为只读的7. 永久挂…

[AI助力] 2022.2.23 考研英语学习 2010 英语二翻译

[AI助力] 2022.2.23 考研英语学习 2010 英语二翻译 文章目录[AI助力] 2022.2.23 考研英语学习 2010 英语二翻译2010年英语二翻译真题自己写的积累&#x1f9d0;看看AI的翻译&#xff0c;学习学习&#xff08;把自己当成阅卷老师来康康hhh&#x1f920;DeepL谷歌翻译ReadPaper里…

JavaUDP通信程序

2 UDP通信程序 2.1 UDP通信原理 UDP协议是一种不可靠的网络协议&#xff0c;它在通信的两端各建立一个Socket对象, 但是这两个Socket只是发送&#xff0c;接收数据的对象因此对于基于UDP协议的通信双方而言,没有所谓的客户端和服务器的概念 Java提供了DatagramSocket类作为基…

低代码选型,论协同开发的重要性

Git是一款用于分布式版本控制的免费开源软件: 它可以跟踪到所有文件集中任意的变更&#xff0c;通常用于在软件开发期间&#xff0c;协调配合程序员之间的代码程序开发工作。 Git 最初诞生的原因源于Linux 内核的开发&#xff0c;2005年Linus Torvalds 编写出了Git。其他内核开…

AI作画—中国画之山水画

山水画&#xff0c;简称“山水”&#xff0c;中国画的一种&#xff0c;描写山川自然景色为主体的绘画。山水画在我国绘画史中占有重要的地位。 山水画形成于魏晋南北朝时期&#xff0c;但尚未从人物画中完全分离。隋唐时始终独立&#xff0c;五代、北宋时趋于成熟&#xff0c;…

Solon2 之基础:四、应用启动过程与完整生命周期

串行的处理过程&#xff08;含六个事件扩展点 两个函数扩展点&#xff09;&#xff0c;代码直接、没有什么模式。易明 提醒&#xff1a; 启动过程完成后&#xff0c;项目才能正常运行&#xff08;启动过程中&#xff0c;不能把线程卡死了&#xff09;AppBeanLoadEndEvent 之前…

【C++】类和对象(完结篇)

文章目录1. 再谈构造函数1.1 初始化列表1.2 explicit关键字2. static 成员2.1 静态成员变量2.1 静态成员函数2.3 练习2.4 总结3. 匿名对象4. 友元4.1 友元函数4.2 友元类5. 内部类6. 拷贝对象时编译器的一些优化7. 再次理解类和对象这篇文章呢&#xff0c;我们来再来对类和对象…

TypeScript学习笔记(一)编译环境、数据类型、函数类型、联合类型

文章目录编译环境基本类型函数类型函数重载联合类型和函数重载编译环境 TypeScript最终会被编译成JavaScript来运行&#xff0c;所以我们需要搭建对应的环境。 首先我们要全局安装typescript # 安装命令 npm install typescript -g # 查看版本 tsc --version⭐️ 方式一&…

【2023-2-23】FastDeploy 安装教程

【2023-2-22】FastDeploy 安装编译教程 该测试 FastDeploy CPU版本。 1. fastDeploy库编译 1.1 官方预编译库下载 预编译库下载安装 1.2 自定义CPU版本库编译 官方编译FastDeploy教程 CMakeGUI VS 2019 IDE编译FastDeploy 本人编译教程 CMAKE_CONFIGURATION_TYPES 属性设…

(三十一)大白话MySQL如果事务执行到一半要回滚怎么办?再探undo log回滚日志原理

之前我们已经给大家深入讲解了在执行增删改操作时候的redo log的重做日志原理&#xff0c;其实说白了&#xff0c;就是你对buffer pool里的缓存页执行增删改操作的时候&#xff0c;必须要写对应的redo log记录下来你做了哪些修改 如下图所示&#xff1a; 这样万一要是你提交事…

渗透测试之DNS域名信息探测实验

渗透测试之DNS域名信息探测实验实验目的一、实验原理1.1 域名1.2 .域名的构成1.3 域名的基本类型1.4 域名级别二、实验环境2.1 操作机器三、实验步骤1. 使用sp查询域名信息2. 进行探测实验实验目的 掌握使用nslookup进行DNS域名信息探测的原理和方式了解子域名查询网站 一、实…

PCB封装孔小,元器件无法插入,如何解决?

DIP就是插件&#xff0c;采用这种封装方式的芯片有两排引脚&#xff0c;可以直接焊在有DIP结构的芯片插座上或焊在有相同焊孔数的焊位中。其特点是可以很方便地实现PCB板的穿孔焊接&#xff0c;和主板有很好的兼容性。但是由于其封装面积和厚度都比较大&#xff0c;而且引脚在插…