光線追蹤
阿新 • • 發佈:2018-11-01
題目描述
考慮一個二維平面,攝像機在(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; }