|
题目链接:http://poj.org/problem?id=2528

 /**//*
题意:
给定N(N <= 10000)块木板,依次层叠,问最后能从上方俯视的木板的数量。


解法:
线段树(染色问题)

思路:
这题是pku 2777的简化版,木板的数量最多10000种,每个结点都保存下来
似乎有点力不从心,但是因为插入是多次,而询问只有一次,所以我们只要保证
插入是O(logn)的,而询问可以O(n),这样问题就变得简单许多,线段树结点保存
一个Cover域,初始化为0,表示是0号木板(输入数据的木板编号从1开始),每
次插入时只更新到完全覆盖的区间,如果当前结点的左右儿子的木板颜色不同,
那么它的Cover域就是-1,否则是木板的下标。询问的时候如果遇到Cover域为-1
的结点则递归它的子结点,否则统计。
*/

#include <iostream>
#include <algorithm>
using namespace std;

#define maxn 100010

int tmp[maxn], tmpsize;
int bin[maxn], size;

 struct Interval {
int l, r;
}I[maxn];

 struct Tree {
int nCover;
int son[2];

 void clear() {
son[0] = son[1] = -1;
nCover = 0;
}
}T[ maxn*4 ];
int root, tot = 0;

 int GetId(int& root) {
 if(root == -1) {
root = tot++;
T[root].clear();
}
return root;
}

 void Discretization() {
sort(tmp, tmp + tmpsize);
bin[ size = 1 ] = tmp[0];
int i;
 for(i = 1; i < tmpsize; i++) {
if(tmp[i] != tmp[i-1])
bin[ ++size ] = tmp[i];
}
}

 int Binary(int v) {
int l = 1;
int r = size;
 while(l <= r) {
int m = (l + r) >> 1;
if(bin[m] == v)
return m;
 if(v > bin[m]) {
l = m + 1;
}else
r = m - 1;
}
}

int hash[ maxn ], Case;

 void Insert(int& root, int nl, int nr, int l, int r, int val) {
if(nl > r || nr < l)
return ;

GetId(root);
 if(nl <= l && r <= nr) {
T[root].nCover = val;
return ;
}

 if(T[root].nCover != -1) {
int i;
 for(i = 0; i < 2; i++) {
int idx = GetId(T[root].son[i]);
T[idx].nCover = T[root].nCover;
}
T[root].nCover = -1;
}

int mid = (l + r) >> 1;
Insert(T[root].son[0], nl, nr, l, mid, val);
Insert(T[root].son[1], nl, nr, mid+1, r, val);
}

 void Query(int root, int l, int r) {
if(root == -1)
return ;
 if(T[root].nCover != -1) {
hash[ T[root].nCover ] = Case;
return ;
}
int mid = (l + r) >> 1;
Query(T[root].son[0], l, mid);
Query(T[root].son[1], mid+1, r);
}

 int main() {
int t, i;
int n;
scanf("%d", &t);
 while(t--) {
Case ++;
tmpsize = 0;
scanf("%d", &n);
 for(i = 0; i < n; i++) {
scanf("%d %d", &I[i].l, &I[i].r);
tmp[ tmpsize ++ ] = I[i].l;
tmp[ tmpsize ++ ] = I[i].r;
}
Discretization();
root = -1;
tot = 0;
 for(i = 0; i < n; i++) {
I[i].l = Binary(I[i].l);
I[i].r = Binary(I[i].r);
//printf("<%d %d>\n", I[i].l, I[i].r);
Insert(root, I[i].l, I[i].r, 1, size, i+1);
}
int nCount = 0;
Query(root, 1, size);
 for(i = 1; i <= size; i++) {
if(hash[i] == Case)
nCount ++;
}
printf("%d\n", nCount);
}
return 0;
}
|