[CSP-S模拟测试]:光线追踪(线段树)
题目背景
初中时的乔猫试着组建了$NEWorld$开发组,可是不久之后却因为合作上的问题(和乔猫工程水平差,代码混乱的问题),开发组成员之间常常产生矛盾,关系越来越不如以前......一年下来,受到长期挫折的乔猫最终放弃了$NEWorld$,决定在信息竞赛方面努力奋斗......
是一年过去,上了高中的乔猫突发奇想,决定自己尝试写一个基于八叉树$BVH$(空间细分)的光线追踪渲染器。为了向自己的中二时代致敬,渲染的模型也是一个“方块组成的世界”......同样,为了简化,这里只考虑二维的情况......(貌似简化太多了吧$233$)
题目描述
考虑一个二维平面,摄像机在$(0,0)$的位置,初始时平面上没有障碍物。现在执行$Q$次操作,操作有两种(假设这是第$i$次操作,$1\leqslant i\leqslant Q$):
$1.$给定$x_0,y_0,x_1,y_1(x_0<x_1,y_0<y_1)$,创建一个每条边与坐标轴平行的长方形障碍物,包含所有满足$x_0\leqslant x\leqslant x_1$且$y_0\leqslant y\leqslant y_1$的点$(x,y)$(如果这个区域的某一部分已经存在障碍,则直接覆盖掉它,具体请看样例)。这个障碍物的编号为$i$。
$2.$给定向量$(x,y)$,会有一个动点从摄像机所在的$(0,0)$位置出发,以$(x,y)$所指的方向前进,直到碰到第一个障碍物为止。
对于第$2$种操作,输出最先碰到的障碍物的编号。若不会碰到任何障碍物,输出$0$。
输入格式
输入文件名为$raytracing.in$。
输入文件第一行一个正整数$Q$,表示操作总数。
接下来的$Q$行,每行第一个正整数$op_i$为操作种类(保证为$1$或$2$)。如果为$1$,则接下来四个正整数$x_0,y_0,x_1,y_1(x_0<x_1,y_0<y_1)$表示障碍的位置;如果为 $2$,则接下来两个正整数$x,y$表示前进方向。
输出格式
输出文件名为$raytracing.out$。
输出文件包含$R$行($R$为第$2$种操作的总数),每行一个正整数,表示第一个碰到的障碍物编号。
样例
样例输入:
10
1 3 3 10 4
1 4 2 5 6
2 6 2
1 2 8 4 10
1 0 6 3 9
2 5 2
2 8 6
2 2 9
2 4 7
1 5 7 10 10
样例输出:
1
2
2
5
0
数据范围与提示
样例解释:
在$9$次操作之后,平面的一部分如图所示(箭头为所有第$2$种操作询问的路线)。
数据范围:
对于$30\%$的数据:$Q\leqslant 1,000$。
对于另外$30\%$的数据:$0\leqslant x_0,y_0,x_1,y_1,x,y\leqslant 200$。
对于$100\%$的数据:$Q\leqslant 10^5,0\leqslant x_0,y_0,x_1,y_1,x,y\leqslant 10^9,x_0<x_1,y_0<y_1;x_0$和$y_0$不全为$0$,$x$和$y$不全为$0$。
题解
撞上无非就分两种情况:
$\alpha.$撞底下。
$\beta.$撞左边。
那么开两棵线段树分别维护最早的撞上的是哪个就好了。
注意斜率是$90$度的时候不要除$0$,还有如果同时撞上多个的话输出编号最大的就好了(我也不知道为什么额……)
时间复杂度:$\Theta(Q\log Q)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h>
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
const double eps=-1e-5;
struct rec{int opt,x0,y0,x2,y2;}e[100001];
map<double,int> mp;
int Q;
int cnt,top;
pair<int,int> tr[400001][2],ansx,ansy;
double slope[300001];
double getslope(int x,int y){return x?(double)y/x:0x3f3f3f3f;}
void build(int x,int l,int r)
{
tr[x][0].first=tr[x][1].first=0x3f3f3f3f;
if(l==r)return;
int mid=(l+r)>>1;
build(L(x),l,mid);
build(R(x),mid+1,r);
}
void add(int x,int l,int r,int L,int R,int w,int id,int p)
{
if(r<L||R<l)return;
if(L<=l&&r<=R){if(w<=tr[x][p].first)tr[x][p]=make_pair(w,id);return;}
int mid=(l+r)>>1;
add(L(x),l,mid,L,R,w,id,p);
add(R(x),mid+1,r,L,R,w,id,p);
}
void ask(int x,int l,int r,int k)
{
if(tr[x][0].first<ansx.first)ansx=tr[x][0];
if(tr[x][0].first==ansx.first)ansx.second=max(ansx.second,tr[x][0].second);
if(tr[x][1].first<ansy.first)ansy=tr[x][1];
if(tr[x][1].first==ansy.first)ansy.second=max(ansy.second,tr[x][1].second);
if(l==r)return;
int mid=(l+r)>>1;
if(k<=mid)ask(L(x),l,mid,k);
else ask(R(x),mid+1,r,k);
}
int main()
{
scanf("%d",&Q);
for(int i=1;i<=Q;i++)
{
scanf("%d",&e[i].opt);
if(e[i].opt==1)
{
scanf("%d%d%d%d",&e[i].x0,&e[i].y0,&e[i].x2,&e[i].y2);
slope[++top]=getslope(e[i].x0,e[i].y0);
slope[++top]=getslope(e[i].x2,e[i].y0);
slope[++top]=getslope(e[i].x0,e[i].y2);
}
if(e[i].opt==2)
{
scanf("%d%d",&e[i].x0,&e[i].y0);
slope[++top]=getslope(e[i].x0,e[i].y0);
}
}
sort(slope+1,slope+top+1);
for(int i=top;i;i--)
{
if(!mp[slope[i]])cnt++;
mp[slope[i]]=cnt;
}
build(1,1,cnt);
for(int i=1;i<=Q;i++)
{
if(e[i].opt==1)
{
add(1,1,cnt,mp[getslope(e[i].x0,e[i].y0)],mp[getslope(e[i].x2,e[i].y0)],e[i].y0,i,0);
add(1,1,cnt,mp[getslope(e[i].x0,e[i].y2)],mp[getslope(e[i].x0,e[i].y0)],e[i].x0,i,1);
}
else
{
ansx=ansy=make_pair(0x3f3f3f3f,0);
ask(1,1,cnt,mp[getslope(e[i].x0,e[i].y0)]);
if(!ansx.second||!ansy.second)printf("%d\n",ansx.second+ansy.second);
else
{
if(!getslope(e[i].x0,e[i].y0))
{
if(e[ansx.second].x0<e[ansy.second].x0||ansx.second<ansy.second)printf("%d\n",ansx.second);
else printf("%d\n",ansy.second);continue;
}
if(getslope(e[i].x0,e[i].y0)==0x3f3f3f3f)
{
if(e[ansx.second].y0<e[ansy.second].y0||ansx.second<ansy.second)printf("%d\n",ansx.second);
else printf("%d\n",ansy.second);continue;
}
if(ansx.first==ansy.first*getslope(e[i].x0,e[i].y0))printf("%d\n",max(ansx.second,ansy.second));
if(ansx.first<ansy.first*getslope(e[i].x0,e[i].y0))printf("%d\n",ansx.second);
if(ansx.first>ansy.first*getslope(e[i].x0,e[i].y0))printf("%d\n",ansy.second);
}
}
}
return 0;
}
rp++
[CSP-S模拟测试]:光线追踪(线段树)的更多相关文章
- 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并
题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...
- 【8.26校内测试】【重构树求直径】【BFS模拟】【线段树维护DP】
题目性质比较显然,相同颜色联通块可以合并成一个点,重新建树后,发现相邻两个点的颜色一定是不一样的. 然后发现,对于一条链来说,每次把一个点反色,实际上使点数少了2个.如下图 而如果一条链上面有分支,也 ...
- [CSP-S模拟测试]:影魔(树状数组+线段树合并)
题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...
- BZOJ2040[2009国家集训队]拯救Protoss的故乡——模拟费用流+线段树+树链剖分
题目描述 在星历2012年,星灵英雄Zeratul预测到他所在的Aiur行星在M天后会发生持续性暴雨灾害,尤其是他们的首都.而Zeratul作为星灵族的英雄,当然是要尽自己最大的努力帮助星灵族渡过这场 ...
- 2018.10.20 NOIP模拟 蛋糕(线段树+贪心/lis)
传送门 听说是最长反链衍生出的对偶定理就能秒了. 本蒟蒻直接用线段树模拟维护的. 对于第一维排序. 维护第二维的偏序关系可以借助线段树/树状数组维护逆序对的思想建立权值线段树贪心求解. 代码
- CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】
正题 题目链接:https://www.luogu.com.cn/problem/CF280D 题目大意 一个长度为\(n\)的序列,\(m\)次操作 修改一个数 询问一个区间中选出\(k\)段不交子 ...
- 【NOIP模拟】board(线段树维护二进制,树序号化为二进制)
题目背景 SOURCE:NOIP2016-RZZ-2 T3 题目描述 给出这样一棵“二叉树”: 每个节点有左右两个儿子,并如下定义每个节点的高度:假设父亲节点的高度为 h ,那么他的两个儿子的节点的高 ...
- BZOJ.3638.CF172 k-Maximum Subsequence Sum(模拟费用流 线段树)
题目链接 各种zz错误..简直了 /* 19604kb 36292ms 题意:选$k$段不相交的区间,使其权值和最大. 朴素线段树:线段树上每个点维护O(k)个信息,区间合并时O(k^2),总O(mk ...
- 2018.06.26 NOIP模拟 纪念碑(线段树+扫描线)
题解: 题目背景 SOURCE:NOIP2015−GDZSJNZXSOURCE:NOIP2015-GDZSJNZXSOURCE:NOIP2015−GDZSJNZX(难) 题目描述 2034203420 ...
随机推荐
- Python 之父 63 岁才退休,我 23 就中年危机。。
Java技术栈 www.javastack.cn 优秀的Java技术公众号 Python 之父 Guido van Rossum 在推特公布了自己从 Dropbox 公司离职的消息,并表示已经退休. ...
- springboot2.0自适应效果错误响应
实现效果当访问thymeleaf渲染页面时,显示的是自定义的错误页面 当以接口方式访问时,显示的是自定义的json数据响应 1. 编写自定义异常 package cn.jfjb.crud.except ...
- npm命令的使用
本人实际项目开发前端用的是单页vue组件开发.不管是启动项目还是下载依赖,都要使用npm命令. 东凑凑,西拼拼,整理些常用的. 前提:需要下载node.js.这里就不详细说明了.具体参照官方文档. 1 ...
- mybatis一对一关联关系映射
mybatis一对一关联关系映射 在关联关系中,有一对一,一对多,多对多三种关联关系. 一对一关系:在操作上,任意一方引入对方的主键作为外键. 一对多关系:在"多"的一方添加&qu ...
- DEV第三方控件的GalleryControl控件
1.获取选中的图片 List<GalleryItem> lstArray = gclImage.Gallery.GetCheckedItems(); 2.滚动到GalleryControl ...
- Adobe cc2019全家桶(免破解直接安装版)
图片来源:Adobe官网 此次整理了Adobe cc2019的全家桶,全部为免破解,直接安装即可使用版本,对一些小白来说,值得推荐. 下载方式:找到下面你需要的Adobe软件,公众号内回复对应的关键词 ...
- nodejs express 上传文件自定义文件名和上传路径
1.客户端 <form action="http://localhost:3000/profile" method="post" enctype=&quo ...
- Linux系统nmtui/nmcli绑定双网卡为team
今天给大家带来图形化界面网络配置工具—nmtui的使用方法,可以省去敲命令的繁琐,较少误操作,结果更加直观. 小知识: nmtui:Network Manager Text User Interfac ...
- linux 下shell中if的“-e,-d,-f”的用法
文件表达式-e filename 如果 filename存在,则为真-d filename 如果 filename为目录,则为真 -f filename 如果 filename为常规文件,则为真-L ...
- Webdriver处理页面元素的方式
Webdriver执行JavaScript代码的方式 WebDriver driver = new ChromeDriver(); JavascriptExecutor jse = (Javascri ...