又一道线段树!对于数据量比较小,区间长度比较大的,一般都需要离散化来实现。
类别:求区间里有多少种不同的覆盖。
解题思路:先读入数据,将每个区间的两个端点都记为两个点,排序,将相同的点去掉。开始初始化线段树,每次更新,就是新插入个区间,二分查找,找到两个端点对应下标,对他们进行区间修改,剩下处理部分与pku2777相似,就不多说了,而且2777那题可以不用位运算,也可以像这题一样,用一个数组标记,判断用了哪几种cover值。
#include < stdio.h >
#include < string .h >
#include < stdlib.h >
#define NN 10000
struct node{
int l, r, cover;
}st[NN * 16 ];
int index, f[ 2 * NN + 4 ], seg[NN][ 2 ];
char mark[NN * 2 + 4 ];
int cmp( const void * a, const void * b){
int * aa = ( int * )a;
int * bb = ( int * )b;
return * aa - * bb;
}
int Find( int x){
int low = 0 ;
int hig = index - 1 ;
do {
int mid = (low + hig) >> 1 ;
if (x == f[mid]){
return mid;
} else if (x > f[mid]){
low = mid + 1 ;
} else {
hig = mid - 1 ;
}
} while (low <= hig);
}
void Init( int l, int r, int id){
st[id].l = l;
st[id].r = r;
st[id].cover = 0 ;
if (r - l <= 1 ){
return ;
}
int mid = (l + r) >> 1 ;
Init(l, mid, id * 2 );
Init(mid, r, id * 2 + 1 );
}
void Update( int l, int r, int key, int id){
if (st[id].l == l && st[id].r == r){
st[id].cover = key;
return ;
}
if (st[id].cover > 0 ){
st[id * 2 ].cover = st[id].cover;
st[id * 2 + 1 ].cover = st[id].cover;
st[id].cover = 0 ;
}
int mid = (st[id].l + st[id].r) >> 1 ;
if (r <= mid){
Update(l, r, key, id * 2 );
} else if (l >= mid){
Update(l, r, key, id * 2 + 1 );
} else {
Update(l, mid, key, id * 2 );
Update(mid, r, key, id * 2 + 1 );
}
}
void Search( int l, int r, int id){
if (st[id].cover > 0 ){
mark[st[id].cover] = 1 ;
return ;
}
int mid = (st[id].l + st[id].r) >> 1 ;
if (r <= mid){
Search(l, r, id * 2 );
} else if (l >= mid){
Search(l, r, id * 2 + 1 );
} else {
Search(l, mid, id * 2 );
Search(mid, r, id * 2 + 1 );
}
}
int main()
{
int T, n, i, t, l, r, ans;
scanf( " %d " , & T);
while (T -- ){
scanf( " %d " , & n);
index = 0 ;
for (i = 0 ; i < n; i ++ ){
scanf( " %d%d " , & seg[i][ 0 ], & seg[i][ 1 ]);
f[index ++ ] = seg[i][ 0 ];
f[index ++ ] = seg[i][ 1 ];
}
t = 1 ;
qsort(f, index, sizeof (f[ 0 ]), cmp);
for (i = 1 ; i < index; i ++ ){
if (f[i] != f[i - 1 ]){
f[t ++ ] = f[i];
}
}
index = t;
Init( 0 , index, 1 );
for (i = 0 ; i < n; i ++ ){
l = Find(seg[i][ 0 ]);
r = Find(seg[i][ 1 ]);
Update(l, r + 1 , i + 1 , 1 );
}
memset(mark, 0 , sizeof (mark));
Search( 0 , index, 1 );
ans = 0 ;
for (i = 1 ; i <= n; i ++ ){
if (mark[i]){
ans ++ ;
}
}
printf( " %d\n " , ans);
}
// system("pause");
return 0 ;
}