Mayor's posters

又一道线段树!对于数据量比较小,区间长度比较大的,一般都需要离散化来实现。

类别:求区间里有多少种不同的覆盖。

解题思路:先读入数据,将每个区间的两个端点都记为两个点,排序,将相同的点去掉。开始初始化线段树,每次更新,就是新插入个区间,二分查找,找到两个端点对应下标,对他们进行区间修改,剩下处理部分与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;
}

 

posted on 2010-07-18 19:52  ylfdrib  阅读(252)  评论(0编辑  收藏  举报