問題:
1. 給定乙個源區間[x,y]和n個無序的目標區間[x1,y1] [x2,y2] ... [xn,yn],判斷源區間[x,y]是不是在目標區間內。
2. 給定乙個視窗區域和系統介面上的n個視窗,判斷這個視窗區域是否被已有的視窗覆蓋。
1. 解法:
先用區間的左邊界值對目標區間進行排序o(nlogn),對排好序的區間進行合併o(n),對每次待查詢的源區間,用二分查出其左右兩邊界點分別處於合併後的哪個源區間中o(logn),若屬於同乙個源區間則說明其在目標區間中,否則就說明不在。
[cpp]view plain
copy
"font-size:18px;"
>#include
#include
using
namespace
std;
struct
line
; #define maxn 10001
line lines[maxn]; // 目標區間
intncnt = 0;
// 合併後區間的個數
#define n 101
line sl[n]; // 待查詢的源區間
// 用二分查詢找出key所在的區間,以區間的low作為劃分
intgetindex(
intkey)
return
v;
} int
main()
lines[ncnt++].high = lasthigh;
for(i=0; i }
2. 解法:
這個問題適合使用線段樹來解答,單次查詢的時間複雜度為o(nlogn),當然也能用陣列解答,但單次查詢的時間複雜度會增加到o(n^2)。這裡我們直接使用線段樹來解答。
線段樹是一棵二叉樹,將數軸劃分成一系列的初等區間[i, i+1] (i=1,2,..,n-1)。每個初等區間對應於線段樹的乙個葉結點。線段樹的內部結點對應於形如[ i, j ](j – i > 1)的一般區間。
由於線段樹給每乙個區間都分配了結點,利用線段樹可以求區間並後的總長度與區間並後的線段數。先給出測試資料(前4行是系統介面上已有的n個視窗,之後的一行是待測試的視窗區域),後面是**: 4
-15 0 5 10
-5 8 20 25
15 -4 24 14
0 -6 16 4
2 15 10 22
[cpp]view plain
copy
#include
#include
#include
using
namespace
std;
// 線段樹的結點
struct
segnode
};
// 構造線段樹,它是乙個完全二叉樹
void
buildsegtree(segnode *&tree,
int*index,
intlow,
inthigh)
} } // 往線段樹中插入線段,即用線段(low,high)來覆蓋線段樹
void
insertsegtree(segnode *tree,
intlow,
inthigh)
} // 從線段樹中刪除線段
void
deletesegtree(segnode *tree,
intlow,
inthigh)
} // 線段樹中是否包含線段(low,high)
bool
findsegtree(segnode *tree,
intlow,
inthigh)
return
false
; }
#define left true
#define right false
#define inf 10000
// 表示豎直方向的線段
struct
line
};
// 所有豎直方向的線段
line lines[inf];
// 對橫向超元線段進行分組
intindex[inf];
intncnt = 0;
// 獲取key的位置
intgetindex(
intkey)
// 獲取key的位置或比它小的最大數的位置
intgetlower(
intkey)
// 獲取key的位置或比它大的最小數的位置
intgetupper(
intkey)
intmain()
// 待查詢的視窗區域
line search[2];
cin >> x[0] >> y[0] >> x[1] >> y[1];
search[0].x=x[0]; search[1].x=x[1];
search[0].starty=search[1].starty=min(y[0],y[1]);
search[0].endy=search[1].endy=max(y[0],y[1]);
search[0].inout=left; search[1].inout=right;
// 對x座標進行排序o(nlogn)
sort(index, index+2*nrec);
sort(lines, lines+2*nrec);
// 排除index陣列中的重複資料o(n)
for(i=1; i<2*nrec; i++)
if(index[i]!=index[i-1])
index[ncnt++] = index[i-1];
index[ncnt++] = index[2*nrec-1];
// 建立線段樹
segnode *tree;
buildsegtree(tree, index, 0, ncnt-1);
// 單詞查詢的時間複雜度為o(nlogn)
bool
res;
insertsegtree(tree, getindex(lines[0].starty), getindex(lines[0].endy));
for(i=1; i<2*nrec; i++)
else
if(search[1].x <= lines[i].x)
break
; }
if(res) printf(
"yes\n"
);
else
printf(
"no\n"
);
return
0;
} 更多0
程式設計之美2 19 區間重合判斷
題目 給定乙個源區間 x,y y x 和n個無序的目標區間 x1,y1 x2,y2 x3,y3 xn,yn 判斷源區間 x,y 是不是在目標區間內?例如,給定源區間 1,6 和一組無序的目標區間 2,3 1,1 3,9 即可認為區間 1,6 在區間 2,3 1,1 3,9 內,因為目標區間實際上是 ...
程式設計之美 2 19 區間重合判斷
題目大意 給定源區間 x,y x y 和 n個無序的目標區間 xi,yi 1 i n 判斷源區間是否在目標區間內。分析 書中介紹了兩種解法。第一種 將目標區間投影到源區間,看最終未被覆蓋的區間是否變為。這種方法的複雜度無疑是很高的。o n 2 另外,對於k組源區間查詢,其複雜度是單次的k倍。第二種 ...
程式設計之美 2 19 區間重合判斷
給定乙個源區間 x,y y x 和n個無序的目標區間 x1,y1 x2,y2 xn,yn 判斷源區間 x,y 是不是在目標區間內 eg,給定乙個源區間 1,6 和一組無序的目標區間 2,3 1,2 3,9 即可認為 1,6 在區間 2,3 1,2 3,9 內 因為目標區間合併之後,實質為 1,9 i...