Official

M - 長方形/Rectangle Editorial by mechanicalpenciI


問題の条件である「長方形 A,B が重なっている」という条件は、重なっている部分の面積の計算式を考えることで、

  • 長方形 A を \(x\) 軸に射影した時の区間と、長方形 B を \(x\) 軸に射影した時の区間の重なりが正の長さを持つ。
  • 長方形 A を \(y\) 軸に射影した時の区間と、長方形 B を \(y\) 軸に射影した時の区間の重なりが正の長さを持つ。

\(2\) 条件をともにみたすとき、かつそのときにみたされるという事ができます。すなわち、この移動は\(x,y\) 軸への射影それぞれについて重なっている時間帯を求めることで答えを求める事ができます。

まず、\(x\) 軸への射影について考えます。 最初に述べたことから、閉区間 \([U_1t+P_1,U_1t+R_1]\)\([U_2t+P_2,U_2t+R_2]\) が正の長さ重なっているような \(t\) (ただし、\(t\geq 0\))の範囲を求められれば良いです。
この条件は \(U_1t+P_1<U_2t+R_2\) かつ \(U_2t+P_2<U_1t+R_1\) であることです。よって、求める \(t\) の範囲は

\[ t= \begin{cases} \max\left(\frac{P_1-R_2}{U_2-U_1} ,0\right) < t < \frac{R_1-P_2}{U_2-U_1} & (U_1<U_2 のとき) \\ \max\left(\frac{P_2-R_1}{U_1-U_2} ,0\right) < t < \frac{R_2-P_1}{U_1-U_2} & (U_1>U_2 のとき) \\ t \geq 0& (U_1=U_2 \;かつ P_1<R_2 \;かつ P_2<R_1 \;のとき) \\ 条件をみたす範囲なし & (U_1=U_2 \;かつ \; (P_1\geq R_2 \; または\; P_2\geq R_1) \;のとき) \\ \end{cases} \]

となります。\(U_1=U_2\) の場合に注意してください。

同様に\(y\) 軸への射影についても、

\[ t= \begin{cases} \max\left(\frac{Q_1-S_2}{V_2-V_1} ,0\right) < t < \frac{S_1-Q_2}{V_2-V_1} & (V_1<V_2 のとき) \\ \max\left(\frac{Q_2-S_1}{V_1-V_2} ,0\right) < t < \frac{S_2-Q_1}{V_1-V_2} & (V_1>V_2 のとき) \\ t \geq 0& (V_1=V_2 \;かつ Q_1<S_2 \;かつ Q_2<S_1 \;のとき) \\ 条件をみたす範囲なし & (V_1=V_2 \;かつ \; (Q_1\geq S_2 \; または\; Q_2\geq S_1) \;のとき) \\ \end{cases} \]

と求める事ができるため、あとはこの \(2\) つの共通部分の長さを求めれば良いです。共通部分は存在する場合は必ず区間となり左右端の時刻は、 \(O(1)\) で計算できるため、よって、この問題を解く事ができました。

c++ による実装例

#include <bits/stdc++.h>
using namespace std;

#define INF (double)1e+100
#define EPS (double)1e-9

int main(void) {
	double p[2][2],q[2][2],u[2][2],x,y;
	cin>>p[0][0]>>p[1][0]>>q[0][0]>>q[1][0]>>u[0][0]>>u[1][0];
	cin>>p[0][1]>>p[1][1]>>q[0][1]>>q[1][1]>>u[0][1]>>u[1][1];
	x=0,y=INF;
	for(int i=0;i<2;i++){
		if(u[i][0]<u[i][1]){
			x=max(x,(p[i][0]-q[i][1])/(u[i][1]-u[i][0]));
			y=min(y,(q[i][0]-p[i][1])/(u[i][1]-u[i][0]));
		}
		else if(u[i][0]>u[i][1]){
			x=max(x,(p[i][1]-q[i][0])/(u[i][0]-u[i][1]));
			y=min(y,(q[i][1]-p[i][0])/(u[i][0]-u[i][1]));
		}
		else{
			if(max(p[i][0],p[i][1])+EPS>=min(q[i][0],q[i][1]))x=INF,y=0;
		}
	}
	cout<< std::fixed << std::setprecision(10) <<max(0.0,y-x)<<endl;
}

posted:
last update: