题目
思路
分治,每一个矩形都有一个轮廓图,不妨设它的能代表轮廓线的三个点从左到右存在一张线性表中,当有两个矩形要求其轮廓线一共分为以下几种情况:
- 两个矩形没有交集,靠左的矩形的右边界小于靠右矩形的左边界,即 R l < L r R_l<L_r Rl<Lr;
- 两个矩形边相切,靠左的矩形的右边界等于靠右矩形的左边界,即 R l = = L r R_l==L_r Rl==Lr;
- 两个矩形边相交,靠左的矩形的右边界大于靠右矩形的左边界,即 R l > L r R_l>L_r Rl>Lr;
- 两个矩形边内含,即在相交的基础上 R l < L l R_l<L_l Rl<Ll。
关于上述操作,1,2两点直接push_back即可,而对于3,4则是要在两个的交集域中再次更新轮廓线的高度以及某小段的宽度,于是根据上述逻辑,两个轮廓线的合并操作也一致。
于是我们可以利用分治,把整个区间不断均分成两份,当区间剩1份矩形使直接返回这个矩形的轮廓线;当区间剩2份矩形时返回他们合并后的轮廓线;否则继续平分。
复杂度分析: T ( n ) = 2 ∗ T ( n / 2 ) + n T(n)=2*T(n/2)+n T(n)=2∗T(n/2)+n,平均复杂度为: O ( n ∗ l o g 2 n ) O(n*log2^n) O(n∗log2n)
伪代码
LinkList<int> Divide(RectList arr[], int l, int r) {
if(r == l) return make_profile(arr[l]);
if(r == l+1) return make_profile(merge(arr[l], arr[r]));
int mid = l + (r - l >> 1); //中点
return make_profile(merge(Divide(arr, l, mid), Divide(arr, mid+1, r)));
}