• 光线追踪(raytracing)


    光线追踪(raytracing)

    题目描述

     

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

    1、给定x0,y0,x1,y1(x0<x1,y0<y1)x0,y0,x1,y1(x0<x1,y0<y1),创建一个每条边与坐标轴平行的长方形障碍物,包含所有满足x0≤x≤x1x0≤x≤x1且y0≤y≤y1y0≤y≤y1的点(x,y)(x,y)(如果这个区域的某一部分已经存在障碍,则直接覆盖掉它,具体请看样例)。这个障碍物的编号为ii。

    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<x1,y0<y1)x0,y0,x1,y1(x0<x1,y0<y1)表示障碍的位置;如果为2,则接下来两个正整数x,yx,y表示前进方向。

     

     

    输出

     

     

    输出文件包含RR行(RR为第2种操作的总数),每行一个正整数,表示第一个碰到的障碍物编号。

     

     

    样例输入

    <span style="color:#333333"><span style="color:#333333">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</span></span>

    样例输出

    <span style="color:#333333"><span style="color:#333333">1
    2
    2
    5
    0</span></span>

    提示

     

    样例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<x1,y0<y1Q≤105,0≤x0,y0,x1,y1,x,y≤109,x0<x1,y0<y1;x0x0和y0y0不全为0,xx和yy不全为0。

     

    来源

    noip2018模拟-南外


    好题。

    我一看是计算几何,就方了,

    结果是道线段树。。。

    横纵坐标分开处理

    把所有有用的点按斜率离散化,于是一段线段就变成了一段区间。

    那么修改操作就是区间取Max

    查寻出x,y的最小值然后取较小的(先碰到)

    注意判x, y为0的情况

    本题奇技淫巧:

    线段树不下传标记,查询时每层取Max(ccj线段树?orz)

    把x=x*k化为y来比较而不是y=y/k 避免精度爆炸

    double 开 long double 避免精度爆炸

    或者用atan2

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #define maxn 400005
    #define db long double
    #define inf 2e9
    using namespace std;
    int Q,n,x,y,top,li,ri,pl,ansx,xid,ansy,yid;
    db xl[maxn],kk,k1,k2,k3;
    struct node{
        int op;int xa,ya,xb,yb;
    }s[maxn];
    map<db,int>ls;
    struct no{
        int v,id,l,r;
    }tree[maxn*2][2];
    bool cmp(db aa,db bb){return aa>bb;}
    void build(int k,int L,int R){
        tree[k][0].l=tree[k][1].l=L;tree[k][0].r=tree[k][1].r=R;
        tree[k][0].v=tree[k][1].v=inf;
        if(L==R)return;
        int mid=L+R>>1;
        build(k*2,L,mid);build(k*2+1,mid+1,R);
    }
    void add(int k,int val,int id,int p){
        if(tree[k][p].l>=li&&tree[k][p].r<=ri){
            if(tree[k][p].v>=val){
                tree[k][p].v=val;tree[k][p].id=id;
            }return;
        }
        int mid=tree[k][p].l+tree[k][p].r>>1;
        if(li<=mid)add(k*2,val,id,p);
        if(ri>mid)add(k*2+1,val,id,p);
    }
    void ask(int k){
        if(tree[k][0].v<ansx)ansx=tree[k][0].v,xid=tree[k][0].id;
        if(tree[k][0].v==ansx)xid=max(xid,tree[k][0].id);
        if(tree[k][1].v<ansy)ansy=tree[k][1].v,yid=tree[k][1].id;
        if(tree[k][1].v==ansy)yid=max(yid,tree[k][1].id);
         
        if(tree[k][0].l==tree[k][0].r)return;
        int mid=tree[k][0].l+tree[k][0].r>>1;
        if(pl<=mid)ask(k*2);
        else ask(k*2+1);
    }
     
    db chu(int y,int x){
        if(x==0)return inf;
        db yy=y,xx=x;
        return yy/xx;
    }
    int main()
    {
        cin>>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].xa,&s[i].ya,&s[i].xb,&s[i].yb);
                x=s[i].xa,y=s[i].ya;kk=chu(y,x);xl[++top]=kk;
                x=s[i].xb,y=s[i].ya;kk=chu(y,x);xl[++top]=kk;
                x=s[i].xa,y=s[i].yb;kk=chu(y,x);xl[++top]=kk;
            }
            else {
                scanf("%d%d",&s[i].xa,&s[i].ya);
                x=s[i].xa,y=s[i].ya;kk=chu(y,x);xl[++top]=kk;
            }
        }
        sort(xl+1,xl+top+1,cmp);int tot=0;
        for(int i=1;i<=top;i++){
            if(!ls[xl[i]])ls[xl[i]]=++tot;
        }
        //cout<<top<<' '<<tot<<endl;
        // x tree[0] y tree[1]
        build(1,1,tot);
        for(int i=1;i<=Q;i++){
            if(s[i].op==1){
                x=s[i].xa,y=s[i].ya;k1=chu(y,x);
                x=s[i].xb,y=s[i].ya;k2=chu(y,x);
                x=s[i].xa,y=s[i].yb;k3=chu(y,x);
                li=ls[k1],ri=ls[k2];add(1,s[i].ya,i,0);
                li=ls[k3],ri=ls[k1];add(1,s[i].xa,i,1);
            }
            else {
                x=s[i].xa,y=s[i].ya;k1=chu(y,x);
                pl=ls[k1],ansx=inf,xid=0,ansy=inf,yid=0;
                ask(1);
                if(!xid||!yid)printf("%d
    ",xid+yid);
                else {
                    if(k1==inf){
                        if(s[xid].ya<s[yid].ya||xid<yid)printf("%d
    ",xid);
                        else printf("%d
    ",yid);continue;
                    }
                    if(k1==0){
                        if(s[xid].xa<s[yid].xa||xid<yid)printf("%d
    ",xid);
                        else printf("%d
    ",yid);continue;
                    }
                    double Y=ansy*k1;
                    if(ansx==Y)printf("%d
    ",max(xid,yid));
                    if(ansx<Y)printf("%d
    ",xid);
                    if(ansx>Y)printf("%d
    ",yid);
                }
            }
        }
        return 0;
    }
     
  • 相关阅读:
    SVN安装配置与使用
    ext中对json数据的处理解析
    matlab保存数据
    DLL编程总结
    【MFC 】关于对话框中的OnVScroll() 和 OnHScroll
    OpenCV cvReleaseImage把图像怎么样了?
    [code] if (x<0)x=0;else if (x>255)x=255;
    【DM642学习笔记十】DSP优化记录
    DSP日志打印 LOG_printf
    【MFC】MFC文本框中显示浮点数
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358798.html
Copyright © 2020-2023  润新知