【線段樹】光線追蹤
阿新 • • 發佈:2019-01-08
分析:
其實是很水很水的線段樹題!
可以根據從原點到所有點按極角排序,然後分行/列線段數,分別維護縱/橫座標最小的覆蓋線段。
然後這題就變成了:區間覆蓋,單點詢問最大值問題。
#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);
}
}
}