题解 光线追踪

传送门

首先发现在每个矩形占据的实际上是 \([0, 90°]\) 中的一个区间
区间之间可能存在覆盖关系,于是想用珂朵莉树
但是边分横边和纵边,我不会处理题图中在1上插入一个2的情况,于是炸了

正解的话把横边和纵边分开考虑了
首先把所有出现的向量拿出来离散化
可以利用向量叉乘实现比较角度大小

  • (二维)向量叉乘:\(a\)^\(b=x1y2-x2y1\),方向可以右手定则判断,可以用来比较两个向量的位置关系
    方向判定:
    image image
    另外叉积的绝对值就是A和B为两边所形成的平行四边形的面积,也就是AB所包围三角形面积的两倍
    image
    (图片来源于这里,侵删)

于是变成了区间取min,可以标记永久化实现
特别注意一个细节,斜率为0或1的时候要特判只从纵/横边查询
image

Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n;

namespace force{
	int tot;
	struct rec{int x1, y1, x2, y2, rk; double l, r; inline void build(int a, int b, int c, int d, double e, double f, int rs){x1=a; y1=b; x2=c; y2=d; l=e; r=f; rk=rs;}}r[N];
	void solve() {
		for (int i=1,a,b,c,d,op,x,y; i<=n; ++i) {
			op=read();
			if (op&1) {
				a=read(); d=read(); c=read(); b=read();
				double t1, t2;
				if (!a) t1=1e30;
				else t1=1.0*b/a;
				if (!c) t2=1e30;
				else t2=1.0*d/c;
				// printf("t: %lf %lf\n", t1, t2);
				r[++tot].build(a, b, c, d, t1, t2, i);
				// cout<<"add: "<<tot<<endl;
				// cout<<"xy: "<<a<<' '<<b<<' '<<c<<' '<<d<<endl;
			}
			else {
				x=read(); y=read();
				double tan, k;
				if (!x) tan=k=1e30;
				else tan=k=(1.0*y/x);
				// printf("k: %lf\n", k);
				double minn=1e30; int mini=0;
				for (int j=1; j<=tot; ++j) {
					if (tan>r[j].l || tan<r[j].r) continue;
					double d1, d2, t1, t2, dis;
					d1=r[j].x1, d2=k*r[j].x1;
					t1=sqrt(d1*d1+d2*d2);
					d1=r[j].y2/k, d2=r[j].y2;
					t2=sqrt(d1*d1+d2*d2);
					dis=max(t1, t2)-j*1e-12;
					// printf("dis: %d, %lf\n", j, dis);
					if (dis<=minn) minn=dis, mini=r[j].rk;
				}
				printf("%d\n", mini);
			}
		}
		exit(0);
	}
}

namespace task{
	#undef unix
	int usizx, usizy;
	int op[N], qx1[N], qy1[N], qx2[N], qy2[N], uni[N<<2], usiz;
	struct vec{
		ll x, y;
		vec(){}
		vec(ll a, ll b) {x=a; y=b;}
		inline void build(ll a, ll b) {x=a; y=b;}
		inline ll operator ^ (vec b) {return x*b.y-b.x*y;}
		inline bool operator < (vec b) {return (*this^b)>0;}
		inline bool operator == (vec b) {return (*this^b)==0;}
	}unix[N<<1], uniy[N<<1];
	struct data{
		int ord, num;
		data():ord(INF),num(0){}
		data(int a, int b):ord(a),num(b){}
		inline data operator + (data b) {
			if (ord==b.ord) return num<b.num?b:*this;
			else return ord<b.ord?*this:b;
		}
	};
	struct seg{
		data dat[N<<2];
		int tl[N<<2], tr[N<<2];
		#define tl(p) tl[p]
		#define tr(p) tr[p]
		#define dat(p) dat[p]
		void build(int p, int l, int r) {
			tl(p)=l; tr(p)=r;
			if (l==r) return ;
			int mid=(l+r)>>1;
			build(p<<1, l, mid);
			build(p<<1|1, mid+1, r);
		}
		void upd(int p, int l, int r, data val) {
			if (l<=tl(p)&&r>=tr(p)) {dat(p)=dat(p)+val; return ;}
			int mid=(tl(p)+tr(p))>>1;
			if (l<=mid) upd(p<<1, l, r, val);
			if (r>mid) upd(p<<1|1, l, r, val);
		}
		data query(int p, int pos) {
			if (tl(p)==tr(p)) return dat(p);
			int mid=(tl(p)+tr(p))>>1;
			if (pos<=mid) return dat(p)+query(p<<1, pos);
			else return dat(p)+query(p<<1|1, pos);
		}
	}segx, segy;
	void solve() {
		unix[++usizx].build(1, 0); unix[++usizx].build(0, 1);
		uniy[++usizy].build(1, 0); uniy[++usizy].build(0, 1);
		for (int i=1,a,b,c,d; i<=n; ++i) {
			op[i]=read();
			if (op[i]&1) {
				a=read(); d=read(); c=read(); b=read();
				// cout<<"abcd: "<<a<<' '<<b<<' '<<c<<' '<<d<<endl;
				uni[++usiz]=a; uni[++usiz]=b; uni[++usiz]=c; uni[++usiz]=d;
				qx1[i]=a; qy1[i]=b; qx2[i]=c; qy2[i]=d;
				unix[++usizx].build(a, b); unix[++usizx].build(a, d);
				uniy[++usizy].build(a, d); uniy[++usizy].build(c, d);
			}
			else {
				qx1[i]=read(); qy1[i]=read();
				unix[++usizx].build(qx1[i], qy1[i]); uniy[++usizy].build(qx1[i], qy1[i]);
			}
		}
		sort(unix+1, unix+usizx+1); sort(uniy+1, uniy+usizy+1); sort(uni+1, uni+usiz+1);
		usizx=unique(unix+1, unix+usizx+1)-unix-1; usizy=unique(uniy+1, uniy+usizy+1)-uniy-1; usiz=unique(uni+1, uni+usiz+1)-uni-1;
		// cout<<"unix: "; for (int i=1; i<=usizx; ++i) cout<<unix[i].x<<','<<unix[i].y<<' '; cout<<endl;
		// cout<<"uniy: "; for (int i=1; i<=usizy; ++i) cout<<uniy[i].x<<','<<uniy[i].y<<' '; cout<<endl;
		segx.build(1, 1, usizx); segy.build(1, 1, usizy);
		vec t1, t2; data d1, d2;
		for (int i=1; i<=n; ++i) {
			if (op[i]&1) {
				t1.build(qx1[i], qy2[i]); t2.build(qx1[i], qy1[i]);
				segx.upd(1, lower_bound(unix+1, unix+usizx+1, t1)-unix, lower_bound(unix+1, unix+usizx+1, t2)-unix, data(lower_bound(uni+1, uni+usiz+1, qx1[i])-uni, i));
				t1.build(qx2[i], qy2[i]); t2.build(qx1[i], qy2[i]);
				segy.upd(1, lower_bound(uniy+1, uniy+usizy+1, t1)-uniy, lower_bound(uniy+1, uniy+usizy+1, t2)-uniy, data(lower_bound(uni+1, uni+usiz+1, qy2[i])-uni, i));
				// cout<<"updy: "<<lower_bound(uniy+1, uniy+usizy+1, t1)-uniy<<' '<<lower_bound(uniy+1, uniy+usizy+1, t2)-uniy<<' '<<lower_bound(uni+1, uni+usiz+1, qy2[i])-uni<<' '<<i<<endl;
			}
			else {
				t1=vec(qx1[i], qy1[i]);
				d1=segx.query(1, lower_bound(unix+1, unix+usizx+1, t1)-unix);
				d2=segy.query(1, lower_bound(uniy+1, uniy+usizy+1, t1)-uniy);
				// cout<<"query2: "<<lower_bound(uniy+1, uniy+usizy+1, t1)-uniy<<endl;
				// cout<<"num: "<<d1.num<<' '<<d2.num<<endl;
				// cout<<"i: "<<i<<endl;
				if (!d1.num || !d2.num) printf("%d\n", max(d1.num, d2.num));
				else {
					// cout<<"2:"<<endl;
					t2=vec(uni[d1.ord], uni[d2.ord]);
					if (uni[d1.ord]==0) printf("%d\n", d2.num);
					else if (uni[d2.ord]==0) printf("%d\n", d1.num);
					else if ((t1^t2)<0) printf("%d\n", d2.num);
					else if ((t1^t2)>0) printf("%d\n", d1.num);
					else printf("%d\n", max(d1.num, d2.num));
				}
			}
		}
	}
}

signed main()
{
	freopen("raytracing.in", "r", stdin);
	freopen("raytracing.out", "w", stdout);

	n=read();
	// force::solve();
	task::solve();

	return 0;
}
posted @ 2021-10-20 12:01  Administrator-09  阅读(0)  评论(0编辑  收藏  举报