题目背景

  初中时的乔猫试着组建了$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模拟测试]:光线追踪(线段树)的更多相关文章

  1. 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并

    题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...

  2. 【8.26校内测试】【重构树求直径】【BFS模拟】【线段树维护DP】

    题目性质比较显然,相同颜色联通块可以合并成一个点,重新建树后,发现相邻两个点的颜色一定是不一样的. 然后发现,对于一条链来说,每次把一个点反色,实际上使点数少了2个.如下图 而如果一条链上面有分支,也 ...

  3. [CSP-S模拟测试]:影魔(树状数组+线段树合并)

    题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...

  4. BZOJ2040[2009国家集训队]拯救Protoss的故乡——模拟费用流+线段树+树链剖分

    题目描述 在星历2012年,星灵英雄Zeratul预测到他所在的Aiur行星在M天后会发生持续性暴雨灾害,尤其是他们的首都.而Zeratul作为星灵族的英雄,当然是要尽自己最大的努力帮助星灵族渡过这场 ...

  5. 2018.10.20 NOIP模拟 蛋糕(线段树+贪心/lis)

    传送门 听说是最长反链衍生出的对偶定理就能秒了. 本蒟蒻直接用线段树模拟维护的. 对于第一维排序. 维护第二维的偏序关系可以借助线段树/树状数组维护逆序对的思想建立权值线段树贪心求解. 代码

  6. CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/CF280D 题目大意 一个长度为\(n\)的序列,\(m\)次操作 修改一个数 询问一个区间中选出\(k\)段不交子 ...

  7. 【NOIP模拟】board(线段树维护二进制,树序号化为二进制)

    题目背景 SOURCE:NOIP2016-RZZ-2 T3 题目描述 给出这样一棵“二叉树”: 每个节点有左右两个儿子,并如下定义每个节点的高度:假设父亲节点的高度为 h ,那么他的两个儿子的节点的高 ...

  8. BZOJ.3638.CF172 k-Maximum Subsequence Sum(模拟费用流 线段树)

    题目链接 各种zz错误..简直了 /* 19604kb 36292ms 题意:选$k$段不相交的区间,使其权值和最大. 朴素线段树:线段树上每个点维护O(k)个信息,区间合并时O(k^2),总O(mk ...

  9. 2018.06.26 NOIP模拟 纪念碑(线段树+扫描线)

    题解: 题目背景 SOURCE:NOIP2015−GDZSJNZXSOURCE:NOIP2015-GDZSJNZXSOURCE:NOIP2015−GDZSJNZX(难) 题目描述 2034203420 ...

随机推荐

  1. Python 之父 63 岁才退休,我 23 就中年危机。。

    Java技术栈 www.javastack.cn 优秀的Java技术公众号 Python 之父 Guido van Rossum 在推特公布了自己从 Dropbox 公司离职的消息,并表示已经退休. ...

  2. springboot2.0自适应效果错误响应

    实现效果当访问thymeleaf渲染页面时,显示的是自定义的错误页面 当以接口方式访问时,显示的是自定义的json数据响应 1. 编写自定义异常 package cn.jfjb.crud.except ...

  3. npm命令的使用

    本人实际项目开发前端用的是单页vue组件开发.不管是启动项目还是下载依赖,都要使用npm命令. 东凑凑,西拼拼,整理些常用的. 前提:需要下载node.js.这里就不详细说明了.具体参照官方文档. 1 ...

  4. mybatis一对一关联关系映射

    mybatis一对一关联关系映射 在关联关系中,有一对一,一对多,多对多三种关联关系. 一对一关系:在操作上,任意一方引入对方的主键作为外键. 一对多关系:在"多"的一方添加&qu ...

  5. DEV第三方控件的GalleryControl控件

    1.获取选中的图片 List<GalleryItem> lstArray = gclImage.Gallery.GetCheckedItems(); 2.滚动到GalleryControl ...

  6. Adobe cc2019全家桶(免破解直接安装版)

    图片来源:Adobe官网 此次整理了Adobe cc2019的全家桶,全部为免破解,直接安装即可使用版本,对一些小白来说,值得推荐. 下载方式:找到下面你需要的Adobe软件,公众号内回复对应的关键词 ...

  7. nodejs express 上传文件自定义文件名和上传路径

    1.客户端 <form action="http://localhost:3000/profile" method="post" enctype=&quo ...

  8. Linux系统nmtui/nmcli绑定双网卡为team

    今天给大家带来图形化界面网络配置工具—nmtui的使用方法,可以省去敲命令的繁琐,较少误操作,结果更加直观. 小知识: nmtui:Network Manager Text User Interfac ...

  9. linux 下shell中if的“-e,-d,-f”的用法

    文件表达式-e filename 如果 filename存在,则为真-d filename 如果 filename为目录,则为真 -f filename 如果 filename为常规文件,则为真-L ...

  10. Webdriver处理页面元素的方式

    Webdriver执行JavaScript代码的方式 WebDriver driver = new ChromeDriver(); JavascriptExecutor jse = (Javascri ...