阴影映射(线段树)

实时阴影是电子游戏中最为重要的画面效果之一。在计算机图形学中,通常使用阴影映射方法来实现实时阴影。

游戏开发部正在开发一款 2D 游戏,同时希望能够在 2D 游戏中模仿 3D 游戏的光影效果,请帮帮游戏开发部!

给定 x-y 平面上的 n 个矩形,矩形的边界平行于坐标轴,且可能相互重叠。同时给定点光源的坐标。现有 m 次操作,每次操作添加或删除一个矩形,或询问 x 轴上的一点是否在阴影内。

输入格式

第一行,两个整数 n , m n,m n,m( 1 ≤ n , m ≤ 2 × 1 0 5 1≤n,m≤2×10^5 1n,m2×105)。
第二行,两个整数 l x , l y l_x,l_y lx,ly,表示光源的坐标为 ( l x , l y ) (l_x,l_y) (lx,ly) ∣ l x ∣ ≤ 2 × 1 0 5 , 0 < l y ≤ 2 × 1 0 5 |l_x|≤2×10^5,0<l_y≤2×10^5 lx2×105,0<ly2×105
接下来 n n n 行,每行 5 个整数 i d , x , y , w , h id,x,y,w,ℎ id,x,y,w,h,表示编号为 i d id id 的矩形,左下角坐标为 ( x , y ) (x,y) (x,y),宽为 w w w,高为 h ℎ h
接下来 m m m 行,每行先输入一个正整数 o p t opt opt∈[1,3]。

  • o p t = 1 opt=1 opt=1,则接下来输入 5 个整数 i d , x , y , w , h id,x,y,w,ℎ id,x,y,w,h,表示增加一个编号为 i d id id,且左下角坐标为 ( x , y ) (x,y) (x,y),宽和高为 w w w h ℎ h 的矩形。
  • o p t = 2 opt=2 opt=2,则接下来输入一个整数 i d id id,表示删除编号为 i d id id 的矩形。
  • o p t = 3 opt=3 opt=3,则接下来输入一个整数 p p p,表示查询坐标 ( p , 0 ) (p,0) (p,0) 是否在阴影中。

1 ≤ i d ≤ 4 × 1 0 5 1≤id≤4×10^5 1id4×105
∣ x ∣ ≤ 2 × 1 0 5 , 0 < y ≤ 2 × 1 0 5 |x|≤2×10^5,0<y≤2×10^5 x2×105,0<y2×105
0 < w , h ≤ 2 × 1 0 5 0<w,ℎ≤2×10^5 0<w,h2×105
∣ p ∣ ≤ 1 0 9 |p|≤10^9 p109
保证任意时刻场景中所有矩形的 i d id id 互不相同。保证所有矩形各个顶点的 y y y 坐标一定严格小于光源的 y y y坐标。若询问点在阴影的边界上,仍算作在阴影内。

输出格式

对于每个 o p t = 3 opt=3 opt=3 的询问,若询问的点在阴影中,则输出一行 YES,否则输出一行 NO

样例

input
3 19
4 7
1 1 1 2 1
2 6 1 2 3
3 5 2 4 1
3 -1
3 0
3 2
3 3
3 4
3 5
3 6
3 12
3 13
3 14
1 4 4 5 2 1
3 3
3 4
3 5
3 18
3 19
2 1
3 2
3 3
output
NO
YES
YES
NO
NO
NO
YES
YES
YES
NO
NO
YES
YES
YES
NO
NO
NO

提示

在进行所有修改操作之前,所有矩形的位置如下 (绿色部分为阴影区域):
002.png
在加入一个矩形后,所有矩形的位置如下:
003.png
在删除一个矩形后,所有矩形的位置如下:
004.png

很容易想到利用线段树维护阴影区间,添加阴影即为在[l,r]范围内进行+1操作,删除阴影为-1

但是本题的数据范围过大,特别注意当光源与矩形非常接近时,光线几乎平行于x轴,这时用long long都会存在爆精度问题

所以必须进行离散化

我们可以发现需要用到的坐标是有限的,最多不超过 2 × n + m 2×n+m 2×n+m个坐标点,用到的坐标点为线段端点(l,r)和查询位置p

AC代码如下

注意这题的时间复杂度卡的很死,需要采用IO加速,同时切忌使用STL容器

#include <iostream>
#include <algorithm>
#include <map>
#include <cmath>
using namespace std;
#define int long long
const int max_n = 5e5 + 50;
const int max_m = 5e5 + 50;
const int max_len = 1e6 + 50;
const double eps = 1e-8;typedef struct {int idx, x1, y1, x2, y2;
}node;typedef struct {int opt[6];
}query;typedef struct {double first, second;
}line;int n, m;
node arr[max_n];
query qarr[max_m];
int tmpidx, lineidx;
double tmparr[max_len];
line lines[max_n + max_m];
map<double, int>dict;
int tree[max_len];inline int read() {int x = 0, y = 1; char c = getchar();while (c < '0' || c > '9') {if (c == '-') y = -1;c = getchar();}while (c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}return x * y;
}inline int lowbit(int x) {return x & -x;
}int ask(int p) {int res = 0;for (int i = p; i > 0; i -= lowbit(i)) {res += tree[i];}return res;
}void add(int p, int x) {for (int i = p; i < max_len; i += lowbit(i)) {tree[i] += x;}
}double project(int x, int y) {if (x == arr[0].x1) return x;double k = double(y - arr[0].y1) / double(x - arr[0].x1);double b = k * x - y;return b / k;
}void process(node n) {double l, r, ret;l = r = project(n.x1, n.y1);ret = project(n.x1, n.y2);l = min(l, ret); r = max(r, ret);ret = project(n.x2, n.y1);l = min(l, ret); r = max(r, ret);ret = project(n.x2, n.y2);l = min(l, ret); r = max(r, ret);tmparr[tmpidx++] = l;tmparr[tmpidx++] = r;lines[lineidx++] = line{ l,r };
}inline bool equal(double x, double y) {return fabs(x - y) < eps;
}void discrete() {sort(tmparr, tmparr + tmpidx);int cnt = 0;for (int i = 0; i < tmpidx; i++) {if (i == 0) {dict[tmparr[i]] = ++cnt;continue;}if (tmparr[i] != tmparr[i - 1])dict[tmparr[i]] = ++cnt;}
}signed main() {n = read(); m = read();arr[0].x1 = read();arr[0].y1 = read();int tmpid;int cnt;tmpidx = lineidx = 0;for (cnt = 1; cnt <= n; cnt++) {tmpid = read();arr[tmpid].x1 = read();arr[tmpid].y1 = read();arr[tmpid].x2 = arr[tmpid].x1 + read();arr[tmpid].y2 = arr[tmpid].y1 + read();arr[tmpid].idx = cnt - 1;process(arr[tmpid]);}int optnum;for (int i = 1; i <= m; i++) {qarr[i].opt[0] = read();switch (qarr[i].opt[0]){case 1:tmpid = read();arr[tmpid].x1 = read();arr[tmpid].y1 = read();arr[tmpid].x2 = arr[tmpid].x1 + read();arr[tmpid].y2 = arr[tmpid].y1 + read();arr[tmpid].idx = cnt++ - 1;process(arr[tmpid]);qarr[i].opt[1] = tmpid;break;case 2:qarr[i].opt[1] = read();break;case 3:qarr[i].opt[1] = read();tmparr[tmpidx++] = qarr[i].opt[1];break;default:break;}}discrete();for (int i = 0; i < n; i++) {double l = lines[i].first;double r = lines[i].second;l = dict[l]; r = dict[r];add(l, 1);add(r + 1, -1);}for (int i = 1; i <= m; i++) {if (qarr[i].opt[0] == 1) {int p = qarr[i].opt[1];p = arr[p].idx;double l = lines[p].first;double r = lines[p].second;l = dict[l]; r = dict[r];add(l, 1);add(r + 1, -1);}else if (qarr[i].opt[0] == 2) {int p = qarr[i].opt[1];p = arr[p].idx;double l = lines[p].first;double r = lines[p].second;add(dict[l], -1);add(dict[r] + 1, 1);}else {double p = qarr[i].opt[1];if (ask(dict[p])) { printf("YES\n");}else printf("NO\n");}}return 0;
}

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

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

相关文章

再次学习History.scrollRestoration

再次学习History.scrollRestoration 之前在react.dev的源代码中了解到了这个HIstory的属性&#xff0c;当时写了一篇笔记来记录我对它的理解&#xff0c;现在看来还是一知半解。所以今天打算重新学习一下这个属性&#xff0c;主要从属性以及所属对象的介绍、使用方法&#xff0…

Linux信号:信号的保存

目录 一、信号在内核中的表示 二、sigset_t 2.1sigset_t的概念和意义 2.2信号集操作数 三、信号集操作数的使用 3.1sigprocmask 3.2sigpending 3.3sigemptyset 四、代码演示 一、信号在内核中的表示 实际执行信号的处理动作称为信号 递达(Delivery) 。 信号从产生到递达…

Mysql数据库——DML操作

目录 添加数据&#xff08;INSERT&#xff09; 修改数据&#xff08;UPDATE&#xff09; 删除数据&#xff08;DELETE&#xff09; 添加数据&#xff1a; &#xff08;1). 给指定字段添加数据 &#xff08;2). 给全部字段添加数据 &#xff08;3). 批量添加数据 修改数据: 案例…

【STM32】HAL库点灯

【STM32】HAL库点灯 一、探究目标二、探究原理2.1 ST开发库2.1.1 直接配置寄存器2.1.2 标准外设库2.1.3 HAL库2.2 HAL开发2.2.1 环境配置2.2.2 时钟配置2.2.3 GPIO配置2.2.4 工程创建2.2.5 KEIL代码![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/bf1c95d5c6724a6a…

NextGen Mirth Connect XStream反序列化远程代码执行漏洞(CVE-2023-43208)

0x01 产品简介 NextGen Mirth Connect是是美国NextGen公司的一个医疗集成引擎,主要用于医疗领域的系统集成和数据交换,支持多种协议和标准。 0x02 漏洞概述 NextGen Mirth Connect 4.4.1之前版本存在远程代码执行漏洞,未经身份认证的攻击者可利用该漏洞远程执行代码。 0…

混合组网VS传统网络:智能硬件混合组网优劣势浅要解析

智能硬件混合组网是一种利用多种通信技术相结合的方法&#xff0c;以实现更灵活、更可靠的网络连接。通过蓝牙、Wi-Fi、LoRa、4G相互之间的不同通讯方式&#xff0c;根据应用场景的不同以及现场实际环境&#xff0c;优选最佳物联网混合组网方案&#xff0c;以达到部署最便捷性价…

一张SSL证书如何同时保护多个域名及其子域名?

在互联网时代&#xff0c;数据安全和隐私保护变得至关重要&#xff0c;而SSL证书作为确保网站安全的重要工具&#xff0c;其重要性不言而喻。本文将详细探讨一种特殊的SSL证书——多域名通配符SSL证书&#xff0c;它为网站管理员提供了一种高效、经济的方式来保护多个域名及其子…

MyBatis从入门到“入土“

&#x1f495;喜欢的朋友可以关注一下&#xff0c;下次更新不迷路&#xff01;&#x1f495;(●◡●) 目录 一、Mybatis为何物&#xff1f;&#x1f44c; 二、快速入门&#x1f923; 1、新建项目&#x1f60a; 2、数据库建表&#x1f60a; 3、导入依赖的jar包&#x1f60a;…

Linux学习笔记6

TFTP 服务器搭建和测试 关于TFTP:TFTP&#xff08;Trivial File Transfer Protocol&#xff0c;简单文件传输协议&#xff09;&#xff0c;是一个基于UDP 协议实现 的用于在客户机和服务器之间进行简单文件传输的协议&#xff0c;适合于开销不大、不复杂的应用场合 搭建服务器…

后量子密码的发展和应用

后量子算法&#xff0c;特别是后量子密码(PQC)&#xff0c;是近年来密码学领域的一个热门话题。随着量子计算技术的快速发展&#xff0c;传统的公钥密码算法面临着被量子计算机破解的威胁。为了应对这一挑战&#xff0c;后量子密码应运而生&#xff0c;成为了一种能够抵抗量子计…

【论文笔记】| 蛋白质大模型ProLLaMA

【论文笔记】| 蛋白质大模型ProLLaMA ProLLaMA: A Protein Large Language Model for Multi-Task Protein Language Processing Peking University Theme: Domain Specific LLM Main work&#xff1a; 当前 ProLLM 的固有局限性&#xff1a;&#xff08;i&#xff09;缺乏自然…

Redis篇 在linux系统上安装Redis

安装Redis 在Ubuntu上安装Redis 在Ubuntu上安装Redis 在linux系统中,我们安装Redis,必须先使它有root权限. 那么在linux中,如何切换到root用户权限呢? sudo su 就可切换到用户权限了. 在切换到用户权限后,我们需要用一条命令来搜索Redis相关的软件包 apt search redis 会出现非…

ROS2学习——节点话题通信(2)

目录 一、ROS2节点 1.概念 2.实例 &#xff08;1&#xff09;ros2 run &#xff08;2&#xff09;ros2 node list &#xff08;3&#xff09;remapping重映射 &#xff08;4&#xff09;ros2 node info 二、话题 &#xff08;1&#xff09; ros2 topic list &#xf…

头歌openGauss-存储过程第1关:创建存储过程

编程要求 1、创建第1个存储过程&#xff0c;并调用&#xff1b; 1&#xff09;创建存储过程&#xff0c;查询emp表数据&#xff1b; 2&#xff09;调用存储过程&#xff1b; --创建存储过程&#xff0c;获得计算机&#xff08;cs&#xff09;系学生选课情况并将结果写入临时表t…

人脸识别:基于卷积神经网络(CNN)分类思想的人脸识别系统

本文来自公众号 “AI大道理” —————— 项目配套视频课程&#xff1a; 平台&#xff1a;荔枝微课 链接&#xff1a;十方教育 项目地址&#xff1a;https://github.com/AIBigTruth/CNN_faces_recognition 之前很多人来询问这个项目怎么做&#xff0c;代码跑不起来&#…

USB数据恢复软件:轻松找回U盘重要数据!

USB数据丢失的原因 USB数据丢失有一些常见原因&#xff0c;了解这些原因有利于恢复数据。 文件意外删除病毒攻击软件错误未安全弹出USB设备格式化USB设备 顺便一提&#xff0c;如果你通过快捷键“Ctrl D”删除了数据&#xff0c;那你可以从回收站中还原它们。如果你永久删除…

Isaac Sim仿真平台学习(1)认识Isaac Sim

0.前言 上一个教程中我们下载好了Isaac Sim&#xff0c;这一章我们将来简单了解一下Isaac Sim平台。 isaac Sim仿真平台安装-CSDN博客 1.Isaac Sim是啥&#xff1f; What Is Isaac Sim? — Omniverse IsaacSim latest documentation Isaac Sim是NVDIA Omniverse平台的机器…

【编译原理复习笔记】属性文法

属性文法 也称为属性翻译文法&#xff0c;由 Knuth 提出&#xff0c;以上下文无关文法为基础 &#xff08;1&#xff09;为每个文法符号&#xff08;终结符与非终结符&#xff09;配备相关的属性&#xff0c;代表与该文法符号相关的信息 &#xff08;2&#xff09;属性文法对于…

数据链路层协议——以太网协议

1. 数据链路层 网络层用于将数据从一台主机发送到另一台主机。传输层用于将数据可靠的从一台主机发送到另一台主机。&#xff08;网络层没有保证可靠性的策略&#xff0c;传输过程中可能会出现各种意外&#xff0c;例如&#xff1a;丢包&#xff0c;网络拥塞等。通过传输层可以…

跨域问题的4种解决方案

文章导读 前言 跨域问题指的是在Web开发中&#xff0c;由于浏览器的同源策略限制&#xff0c;当一个网页尝试访问与它不同源&#xff08;协议、域名或端口不同&#xff09;的资源时&#xff0c;可能会遇到安全限制导致无法正常访问的问题。这种策略旨在防止恶意网站读取或修改其…