题目背景

  初中时的乔猫试着组建了$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. C++中的异常处理(上)

    1,C++ 内置了异常处理的语法元素 try ... catch ...: 1,try 语句处理正常代码逻辑: 2,catch 语句处理异常情况: 3,try 语句中的异常由对应的 catch 语句处 ...

  2. C语言数据类型关键字

    最初 K&R 给出的关键字 C90 标准添加的关键字 C99 标准添加的关键字 int signed _Bool long void _Complex short   _Imaginary u ...

  3. 学习WCF之路,长期更新

    我学习WCF之路:创建一个简单的WCF程序   为了使读者对基于WCF的编程模型有一个直观的映像,我将带领读者一步一步地创建一个完整的WCF应用.本应用功能虽然简单,但它涵盖了一个完整WCF应用的基本 ...

  4. scrapy框架设置代理ip,headers头和cookies

    [设置代理ip] 根据最新的scrapy官方文档,scrapy爬虫框架的代理配置有以下两种方法: 一.使用中间件DownloaderMiddleware进行配置使用Scrapy默认方法scrapy s ...

  5. 2019-11-29-Roslyn-通过-Nuget-管理公司配置

    title author date CreateTime categories Roslyn 通过 Nuget 管理公司配置 lindexi 2019-11-29 08:58:52 +0800 201 ...

  6. AIX中文件系统管理

    1.文件系统类型 AIX主要支持的文件系统有: JFS(Journaled  File  Systems)   日志型文件系统     JFS2(Enhanced  Journaled  File S ...

  7. redis数据库到mysql或mongodb数据库

    # -*- coding:utf-8 -*-# item_mongodb.py import redis import pymongo import json def main(): redis_co ...

  8. 开发规范总结-java代码

    java8新特性: 开发的时候适当用一些新特性的语法,可以使代码更简洁.譬如List根据某个属性转map.stream.函数式编程.lambda表达式 有一种场景:两个list一个转map 两个lis ...

  9. Stanford CS229 Machine Learning by Andrew Ng

    CS229 Machine Learning Stanford Course by Andrew Ng Course material, problem set Matlab code written ...

  10. discuz论坛后台部分设置更改之后,清除了缓存网站前台不更新不生效的解决办法

    discuz论坛后台部分设置更改之后,清除了缓存但网站前台不更新不生效的解决办法 在config/config_global.php  把  $_config['memory']['eaccelera ...