1. 程式人生 > >【線段樹】光線追蹤

【線段樹】光線追蹤

在這裡插入圖片描述

分析:

其實是很水很水的線段樹題!
可以根據從原點到所有點按極角排序,然後分行/列線段數,分別維護縱/橫座標最小的覆蓋線段。

然後這題就變成了:區間覆蓋,單點詢問最大值問題。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#define SF scanf
#define PF printf
#define x first
#define y second
#define MAXN 100010
#define
INF 0x3FFFFFFF
using namespace std; typedef long long ll; struct node{ int tag; ll xl,xr,yd,yu,x,y; }que[MAXN]; pair<ll,ll> q[MAXN*4]; bool cmp(pair<ll,ll> a,pair<ll,ll> b){ return a.x*b.y-a.y*b.x<0; } map<pair<ll,ll> ,int>num; int ncnt; int pr[MAXN*32],pl[MAXN*32]
; pair<ll,ll> tree[MAXN*32]; void build(int id,int l,int r){ tree[id]=make_pair(-INF,0); if(l==r) return ; int mid=(l+r)>>1; pl[id]=++ncnt; build(pl[id],l,mid); pr[id]=++ncnt; build(pr[id],mid+1,r); } ll gcd(ll x,ll y){ if(y==0) return x; return gcd(y,x%y); } void change(int id,
int l,int r,int l1,int r1,int tar,ll val){ if(l>=l1&&r<=r1){ tree[id]=max(tree[id],make_pair(val,1ll*tar)); return ; } int mid=(l+r)>>1; if(l1<=mid) change(pl[id],l,mid,l1,r1,tar,val); if(r1>mid) change(pr[id],mid+1,r,l1,r1,tar,val); } pair<ll,ll> find(int id,int l,int r,int pos){ if(l==r) return tree[id]; int mid=(l+r)>>1; if(pos<=mid) return max(find(pl[id],l,mid,pos),tree[id]); else return max(find(pr[id],mid+1,r,pos),tree[id]); } int n; int get_num(ll x,ll y){ ll g=gcd(x,y); x/=g,y/=g; return num[make_pair(x,y)]; } int main(){ SF("%d",&n); int tag,cnt=0; ll xl,xr,yd,yu,x,y; for(int i=1;i<=n;i++){ SF("%d",&tag); que[i].tag=tag; if(tag==1){ SF("%lld%lld%lld%lld",&xl,&yd,&xr,&yu); if(xl>xr) swap(xl,xr); if(yd>yu) swap(yd,yu); que[i].xl=xl,que[i].xr=xr,que[i].yd=yd,que[i].yu=yu; q[++cnt]=make_pair(xl,yd); q[++cnt]=make_pair(xl,yu); q[++cnt]=make_pair(xr,yd); } else{ SF("%lld%lld",&x,&y); que[i].x=x,que[i].y=y; q[++cnt]=make_pair(x,y); } } for(int i=1;i<=cnt;i++){ int g=gcd(q[i].x,q[i].y); q[i].x/=g; q[i].y/=g; } sort(q+1,q+1+cnt,cmp); cnt=unique(q+1,q+1+cnt)-q-1; for(int i=1;i<=cnt;i++) num[q[i]]=i; // for(int i=1;i<=cnt;i++) // PF("[%lld %lld]\n",q[i].x,q[i].y); int rtx=++ncnt; build(rtx,1,cnt); int rty=++ncnt; build(rty,1,cnt); for(int i=1;i<=n;i++){ tag=que[i].tag; if(tag==1){ xl=que[i].xl,xr=que[i].xr,yd=que[i].yd,yu=que[i].yu; // PF("{%lld %lld}|{%lld %lld}\n",xl,xr,yd,yu); int l=get_num(xl,yd); int r=get_num(xr,yd); int d=l; int u=get_num(xl,yu); change(rtx,1,cnt,l,r,i,-yd); change(rty,1,cnt,u,d,i,-xl); } else{ x=que[i].x,y=que[i].y; int id=get_num(x,y); // PF("[%d](%lld %lld)\n",id,x,y); pair<ll,ll> ansx=find(rtx,1,cnt,id); pair<ll,ll> ansy=find(rty,1,cnt,id); // PF("{%lld %lld %lld %lld}\n",-ansx.x,ansx.y,-ansy.x,ansy.y); if(ansx.y!=0&&y!=0&&(ansy.y==0||x==0||-ansx.x*x<-ansy.x*y||(ansx.x*x==ansy.x*y&&ansx.y>=ansy.y))) PF("%lld\n",ansx.y); else PF("%lld\n",ansy.y); } } }