给出n个输入,每个输入都是一个区间,这些区间有可能有重叠,形成区间集合S。现在再给一个区间x,问x是否在S中?
关键是如何合并区间得到S?可以用线段树做,空间O(N),查询时间为O(lg N)。线段树并不一定需要显式的一个“树”结构,不一定需要定义一个结构体。在这里用一个cover数组来模拟。
假设输入为:
1 2
3 4
7 9
11 13
形成的区间为[1,4],[7,9],[11,13].查询1-13每个点是否在区间中。
#include <iostream>
using namespace std;
const int N = 20;
int cover[N*4] = {0};
// 如果父亲==1,则孩子不需要再等于1,用0表示;如果父亲等于0而孩子都等于1,则令父亲等于1,孩子等于0.
void up(int index)
{
if (cover[index] == 1)
cover[index<<1] = cover[(index<<1) + 1] = 0;
else
if(cover[index<<1] == 1 && cover[(index<<1) + 1] == 1)
{
cover[index] = 1;
cover[index<<1] = cover[(index<<1) + 1] = 0;
}
}
// 加入新的区间
void update(int L, int R, int l, int r, int index)
{
if(L <=l && R >=r)
{
cover[index] = 1;
return;
}
int mid = l + (r-l)/2;
if(L <= mid && cover[index<<1] == 0) // 递归左孩子
update(L, R, l, mid, index<<1);
if(R >= mid + 1 && cover[(index<<1) + 1] == 0) // 递归右孩子
update(L, R, mid+1, r, (index<<1) + 1);
up(index);
}
int query(int L, int R, int l, int r, int index) // 查询
{
if (cover[index] == 1) // 如果=1,则说明整个区间都等于1,直接返回1即可
return 1;
else
if (l == r) // 不等于1,而且已经到叶子节点,则返回0即可
return 0;
int mid = l + (r - l)/2;
int re1 = 1, re2 = 1;
if (L <= mid)
re1 = query(L, R, l, mid, index<<1);
if (R >= mid + 1)
re2 = query(L, R, mid + 1, r, (index<<1) + 1);
return re1 && re2;
}
int main()
{
int x = 4, y = 13;
int a,b;
while(x--) // 加入区间
{
cin>>a>>b;
cout<<"输入区间: "<<"["<<a<<","<<b<<"]"<<endl;
update(a,b,1,20,1);
}
int i;
cout<<"cover 数组"<<endl;
for(i=1; i<30; i++)
cout<<cover[i]<<" ";
cout<<endl;
while(y--) // 查询
{
cin>>a>>b;
int r = query(a,b,1,20,1);
cout<<13-y<<" th: "<<"["<<a<<","<<b<<"] "<<(r?"在区间里":"不在区间里")<<endl;
}
return 0;
}
输入文件:
1 2
3 4
7 9
11 13
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
输出:
输入区间: [1,2]
输入区间: [3,4]
输入区间: [7,9]
输入区间: [11,13]
cover 数组
0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0
1 th: [1,1] 在区间里
2 th: [2,2] 在区间里
3 th: [3,3] 在区间里
4 th: [4,4] 在区间里
5 th: [5,5] 不在区间里
6 th: [6,6] 不在区间里
7 th: [7,7] 在区间里
8 th: [8,8] 在区间里
9 th: [9,9] 在区间里
10 th: [10,10] 不在区间里
11 th: [11,11] 在区间里
12 th: [12,12] 在区间里
13 th: [13,13] 在区间里
结果是正确的。