又一道线段树!对于数据量比较小,区间长度比较大的,一般都需要离散化来实现。
类别:求区间里有多少种不同的覆盖。
解题思路:先读入数据,将每个区间的两个端点都记为两个点,排序,将相同的点去掉。开始初始化线段树,每次更新,就是新插入个区间,二分查找,找到两个端点对应下标,对他们进行区间修改,剩下处理部分与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;
}