【线段树】光线追踪

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/85803694

在这里插入图片描述

分析:

其实是很水很水的线段树题!
可以根据从原点到所有点按极角排序,然后分行/列线段数,分别维护纵/横坐标最小的覆盖线段。

然后这题就变成了:区间覆盖,单点询问最大值问题。

#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);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/qq_34454069/article/details/85803694