题解 光线追踪
首先发现在每个矩形占据的实际上是 \([0, 90°]\) 中的一个区间
区间之间可能存在覆盖关系,于是想用珂朵莉树
但是边分横边和纵边,我不会处理题图中在1上插入一个2的情况,于是炸了
正解的话把横边和纵边分开考虑了
首先把所有出现的向量拿出来离散化
可以利用向量叉乘实现比较角度大小
- (二维)向量叉乘:\(a\)^\(b=x1y2-x2y1\),方向可以右手定则判断,可以用来比较两个向量的位置关系
方向判定:
另外叉积的绝对值就是A和B为两边所形成的平行四边形的面积,也就是AB所包围三角形面积的两倍
(图片来源于这里,侵删)
于是变成了区间取min,可以标记永久化实现
特别注意一个细节,斜率为0或1的时候要特判只从纵/横边查询
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;
}