光線追蹤(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\n",xid+yid);
            else {
                if(k1==inf){
                    if(s[xid].ya<s[yid].ya||xid<yid)printf("%d\n",xid);
                    else printf("%d\n",yid);continue;
                }
                if(k1==0){
                    if(s[xid].xa<s[yid].xa||xid<yid)printf("%d\n",xid);
                    else printf("%d\n",yid);continue;
                }
                double Y=ansy*k1;
                if(ansx==Y)printf("%d\n",max(xid,yid));
                if(ansx<Y)printf("%d\n",xid);
                if(ansx>Y)printf("%d\n",yid);
            }
        }
    }
    return 0;
}
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM