光线追踪

题目描述

考虑一个二维平面,摄像机在(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;
}

猜你喜欢

转载自blog.csdn.net/qq_32461955/article/details/83546463