3994: 光线追踪(raytracing)

题目描述

 

考虑一个二维平面,摄像机在(0,0)(0,0)的位置,初始时平面上没有障碍物。现在执行QQ次操作,操作有两种(假设这是第ii次操作,1≤i≤Q1≤i≤Q):

1、给定x0,y0,x1,y1(x0

2、给定向量(x,y)(x,y),会有一个动点从摄像机所在的(0,0)(0,0)位置出发,以(x,y)(x,y)所指的方向前进,直到碰到第一个障碍物为止。

对于第2种操作,输出最先碰到的障碍物的编号。若不会碰到任何障碍物,输出0。

 

输入

 

 

输入文件第一行一个正整数QQ,表示操作总数。

接下来的QQ行,每行第一个正整数opiopi为操作种类(保证为1或2)。如果为1,则接下来四个正整数x0,y0,x1,y1(x0

 

 

输出

 

 

输出文件包含RR行(RR为第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

提示

 

样例2

样例解释

在9次操作之后,平面的一部分如图所示(箭头为所有第2种操作询问的路线)。

数据范围

对于30% 的数据:Q≤1000Q≤1000。

对于另外30% 的数据:0≤x0,y0,x1,y1,x,y≤2000≤x0,y0,x1,y1,x,y≤200。

对于100% 的数据:Q≤105,0≤x0,y0,x1,y1,x,y≤109,x0

 

来源

noip2018模拟-南外

题解:

一个障碍物可以挡住一个范围以内的斜率,依照这个,我们可以以斜率为下标建立一个线段树,里面维护的是斜率为k第一个遇到的障碍物编号。然而我们可能交一个障碍物于侧面或者下面,所以要把横纵坐标分开维护,开两个线段树维护,具体实现比较繁琐,代码实现能力有待提高。。。。。。。

#include
#include
#include
#include
#include
#define eps 1e-6
using namespace std;
typedef double db;
mapdk;
struct Node{int op,x0,y0,x2,y2;}s[100005];
struct node{int l,r,id;double Min;}tre1[1200005],tre2[1200005];
//1 x 2 y
int Q,tot,cnt,iid,mx,my;double xl[500005],vv;
void build(int k,int l,int r)
{
    tre1[k].l=tre2[k].l=l;tre1[k].r=tre2[k].r=r;tre1[k].Min=tre2[k].Min=1e18;
    if(l==r)return;
    int mid=l+r>>1;
    build(k*2,l,mid);build(k*2+1,mid+1,r);
}
void update1(int k,int l,int r,int v,int id)
{
    if(l<=tre1[k].l&&r>=tre1[k].r)
    {
        if(v<=tre1[k].Min)tre1[k].Min=v,tre1[k].id=id;
        return;
    }
    int mid=tre1[k].l+tre1[k].r>>1;
    if(l<=mid)update1(k*2,l,r,v,id);
    if(r>mid)update1(k*2+1,l,r,v,id);
}
void update2(int k,int l,int r,int v,int id)
{
    if(l<=tre2[k].l&&r>=tre2[k].r)
    {
        if(v<=tre2[k].Min)tre2[k].Min=v,tre2[k].id=id;
        return;
    }
    int mid=tre2[k].l+tre2[k].r>>1;
    if(l<=mid)update2(k*2,l,r,v,id);
    if(r>mid)update2(k*2+1,l,r,v,id);
}
void ask1(int k,int t)
{
    if(tre1[k].Min>1;
    if(t<=mid)ask1(k*2,t);
    else ask1(k*2+1,t);
}
void ask2(int k,int t)
{
    if(tre2[k].Min>1;
    if(t<=mid)ask2(k*2,t);
    else ask2(k*2+1,t);
}
int main()
{
    scanf("%d",&Q);
    for(int i=1;i<=Q;++i)
    {
        scanf("%d",&s[i].op);
        if(s[i].op==1)
        {
            scanf("%d%d%d%d",&s[i].x0,&s[i].y0,&s[i].x2,&s[i].y2);
            xl[++tot]=atan2(s[i].y0,s[i].x0);
            xl[++tot]=atan2(s[i].y0,s[i].x2);
            xl[++tot]=atan2(s[i].y2,s[i].x0);
        }
        else
        {
            scanf("%d%d",&s[i].x0,&s[i].y0);
            xl[++tot]=atan2(s[i].y0,s[i].x0);
        }
    }
     
    sort(xl+1,xl+1+tot);
    for(int i=1;i<=tot;++i)if(!dk[xl[i]])dk[xl[i]]=++cnt;
    build(1,1,cnt);
    for(int i=1;i<=Q;++i)
    {
        if(s[i].op==1)
        {
            double t1,t2,t3;
            t1=dk[atan2(s[i].y0,s[i].x0)];t2=dk[atan2(s[i].y0,s[i].x2)];
            t3=dk[atan2(s[i].y2,s[i].x0)];
            update1(1,t1,t3,s[i].x0,i);
            update2(1,t2,t1,s[i].y0,i);
            if(!s[i].x0)
            {
                if(!mx)mx=i;
                if(s[i].y0<=s[mx].y0)mx=i;
            }
            if(!s[i].y0)
            {
                if(!my)my=i;
                if(s[i].x0<=s[my].x0)my=i;
            }
        }
        else
        {
            if(!s[i].x0||!s[i].y0)
            {
                if(!s[i].x0&&s[i].y0)printf("%d\n",mx);
                else if(s[i].x0&&!s[i].y0)printf("%d\n",my);
                else printf("%d\n",max(mx,my));
                continue;
            }
            double t=dk[atan2(s[i].y0,s[i].x0)];
            int iid1,iid2;double xx,kk=(db)s[i].y0/s[i].x0;
            vv=1e18;iid=0;ask1(1,t);
            iid1=iid;xx=(db)vv;
            vv=1e18;iid=0;ask2(1,t);
            iid2=iid;
            if(!iid1||!iid2){printf("%d\n",iid1+iid2);continue;}
            int ans;
            vv/=kk;
            /*if(vv-xx>-eps)ans=iid1;
            else if(xx-vv>-eps)ans=iid2;
            else ans=max(iid1,iid2);*/
            if(vv>xx||(fabs(vv-xx)iid2)) ans=iid1;
            else ans=iid2;
            printf("%d\n",ans);
        }
    }
}

 

你可能感兴趣的:(3994: 光线追踪(raytracing))