1. 程式人生 > >光線追蹤

光線追蹤

題目描述

考慮一個二維平面,攝像機在(0,0)的位置,初始時平面上沒有障礙物。現在執行Q次操作,操作有兩種(假設這是第i次操作,1≤i≤Q):

1、給定x0,y0,x1,y1(x0<x1,y0<y1),建立一個每條邊與座標軸平行的長方形障礙物,包含所有滿足x0≤x≤x1且y0≤y≤y1的點(x,y)(如果這個區域的某一部分已經存在障礙,則直接覆蓋掉它,具體請看樣例)。這個障礙物的編號為ii。

2、給定向量(x,y),會有一個動點從攝像機所在的(0,0)位置出發,以(x,y)所指的方向前進,直到碰到第一個障礙物為止。

對於第2種操作,輸出最先碰到的障礙物的編號。若不會碰到任何障礙物,輸出0。

題解

顯然我們按極角序排一下,再把x軸y軸分開就可以把原題轉換為值域上求最大值的問題。然後考慮合併的時候暴判距離。

程式碼

#include <bits/stdc++.h>
#define maxn 400005
#define lo (o<<1)
#define ro (o<<1|1)
#define mid (l+r>>1)
#define INF 0x3f3f3f3f
#define LL long long
#define eps 1e-7
#define P pair<LL,LL>
#define MP(a,b) make_pair(a,b)
using namespace std;
LL read(){
    LL res,f=1; char c;
    while(!isdigit(c=getchar())) if(c=='-') f=-1; res=(c^48);
    while(isdigit(c=getchar())) res=(res<<3)+(res<<1)+(c^48);
    return res*f;
}
struct NODE{
    LL x,y,id,type;
    bool operator < (const NODE&rhs)const{
        return x*rhs.y-rhs.x*y>0;
    }
    bool operator == (const NODE&rhs)const{
        return x*rhs.y-rhs.x*y==0;
    }
}rk[maxn];
struct TR{
    P mn[maxn<<2],lazy[maxn<<2];
    TR(){
        for(int i=0;i<(maxn<<2);i++) mn[i]=lazy[i]=MP(INF,0);
    }
    void pushdown(int o){
        if(lazy[o].first==INF) return;
        lazy[lo]=min(lazy[lo],lazy[o]);
        lazy[ro]=min(lazy[ro],lazy[o]);
        mn[lo]=min(mn[lo],lazy[o]);
        mn[ro]=min(mn[ro],lazy[o]);
        lazy[o]=MP(INF,0);
    } 
    void pushup(int o){
        mn[o]=min(mn[lo],mn[ro]);
    }
    void update(int o,int l,int r,int ll,int rr,P w){
        if(ll>r || l>rr) return ;
        if(ll<=l && r<=rr){mn[o]=min(mn[o],w); lazy[o]=min(lazy[o],w); return;}
        pushdown(o);
        update(lo,l,mid,ll,rr,w);
        update(ro,mid+1,r,ll,rr,w);
        pushup(o);
    }
    P query(int o,int l,int r,int pos){
        if(pos>r || l>pos) return MP(INF,0);
        if(l==r) return mn[o];
        pushdown(o);
        return min(query(lo,l,mid,pos),query(ro,mid+1,r,pos));
    }
}Xs,Ys;
struct Q{
    LL l,r,w;
}xs[maxn],ys[maxn];
LL n=1,cnt,q,X1[maxn],X2[maxn],Y1[maxn],Y2[maxn],t[maxn];
int main(){
    q=read();
    for(int i=1;i<=q;i++){
        t[i]=read();
        if(t[i]==1){
            X1[i]=read(),Y1[i]=read(),X2[i]=read(),Y2[i]=read();
            rk[++cnt]=(NODE){X1[i],Y1[i],i,1};
            rk[++cnt]=(NODE){X2[i],Y1[i],i,2};
            rk[++cnt]=(NODE){X1[i],Y2[i],i,3};
            xs[i].w=Y1[i]==0?X1[i]:Y1[i];
            ys[i].w=X1[i]==0?Y1[i]:X1[i];
        }
        else {
            X1[i]=read(),Y1[i]=read();
            rk[++cnt]=(NODE){X1[i],Y1[i],i,4};
        }
    }
    sort(rk+1,rk+cnt+1);
    for(int i=1;i<=cnt;i++){
        int p=rk[i]==rk[i-1]?n:++n,type=rk[i].type,id=rk[i].id;
        if(type==1) xs[id].r=p,ys[id].l=p;
        else if(type==2) xs[id].l=p;
        else if(type==3) ys[id].r=p;
        else xs[id].l=p;
    }
    for(int i=1;i<=q;i++){
        if(t[i]==1){
            Xs.update(1,1,n,xs[i].l,xs[i].r,P(xs[i].w,-i));
            Ys.update(1,1,n,ys[i].l,ys[i].r,P(ys[i].w,-i));
        }
        else{
            P ans1=Xs.query(1,1,n,xs[i].l),ans2=Ys.query(1,1,n,xs[i].l);
            if(ans1.second==0 || ans2.second==0) {printf("%lld\n",-ans1.second-ans2.second); continue;}
            long double dis1=1.0*ans1.first/(1.0*Y1[i]);
            long double dis2=1.0*ans2.first/(1.0*X1[i]);
            if(dis1==dis2) printf("%lld\n",max(-ans1.second,-ans2.second));
            else if(dis1<dis2) printf("%d\n",-ans1.second);
            else printf("%lld\n",-ans2.second);
        }
    }
    return 0;
}