#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
/*
对线段树离散化的理解, 把单位区间比较多,但是程序中有用不到那么多单位小区间,这时可以用线段树的离散化来处理,
比如[1 3], [2 10], [4 6], [20 10000000] 可以离散化为
[1 3] [2 7] , [5 6], [8 9]; 这样 我们就可以开一个a[10] 的数组来存储就行了, 节省大量的内存 开支,
离散化 ,白话一点 就是区间按不等 但合理的方式,缩小的产物,
以上为基本思想,其能演变的阵法,就靠自己的变通能力了。
*/
const int M = 10005;
struct node
{
int l, r;
int value;
}Tree[16*M];
int n, T;
int vist[4*M];
int num[4*M];//辅助离散化,
int post[M][2];//存储海报前端和后端,
int num2[4*M];//存储离散化后的数,
int ans;
int Find(int l, int r, int x)
{
int mid;
while(l <= r)
{
mid = (l + r)/2;
if(num2[mid] == x)
return mid;
else if(num2[mid] > x)
{
r = mid - 1;
}
else
{
l = mid + 1;
}
}
return 0;
}
void Make_Tree(int x, int y, int nu)
{
Tree[nu].l = x;
Tree[nu].r = y;
Tree[nu].value = 0;
if(x == y)
return;
else
{
int mid = (x + y)/2;
Make_Tree(x, mid, nu*2);
Make_Tree(mid + 1, y, nu*2 + 1);
}
}
void Add(int x, int y, int c, int nu)
{
if(Tree[nu].l >= x && Tree[nu].r <= y)//整个区间都被覆盖,
{
Tree[nu].value = c;
return ;
}
else
{
int mid;
if(Tree[nu].value > 0)//当前区间如果被覆盖过, 则整个区间都被覆盖着,向下传时,也将覆盖整个子区间,
{
Tree[nu*2].value = Tree[nu].value;
Tree[nu*2 + 1].value = Tree[nu].value;
Tree[nu].value = 0;
}
mid = (Tree[nu].l + Tree[nu].r)/2;//向下查找,当前区间能够覆盖的子区间,
if(x <= mid)
Add(x, y, c, nu*2);
if(y > mid)
Add(x, y, c, nu*2 +1);
}
}
void query(int x, int y, int nu)
{
if(Tree[nu].value > 0) { //表示 此区间当前被覆盖;
int in = Tree[nu].value;
if(!vist[in]) {
ans++;
vist[in] = 1;
}
return;
}
else { //继续查找被覆盖的小区间,
if(x == y)
return;
int mid = (x + y)/2;
query(x, mid, nu*2);
query(mid +1, y, nu*2 + 1);
}
}
int main()
{
scanf("%d", &T);
while(T--)
{
memset(Tree, 0, sizeof(Tree));
memset(num, 0, sizeof(num));
memset(post, 0, sizeof(post));
memset(num2, 0, sizeof(num2));
memset(vist, 0, sizeof(vist));
ans = 0;
scanf("%d", &n);
int k = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &post[i][0], &post[i][1]);
num[++k] = post[i][0];
num[++k] = post[i][1];
}
sort(num + 1, num + k + 1);
k = unique(num + 1, num + k + 1) - num;
k = k - 1;
int kn = 0;
for(int i = 1; i <= k; i++)//离散化;
{
if(i > 1 && num[i] > num[i-1] + 1)
{
num2[++kn] = num[i-1] + 1;
}
num2[++kn] = num[i];
}
Make_Tree(1, kn, 1);
int xn, yn;
for(int i = 1; i <= n; i++)
{
xn = Find(1, kn, post[i][0]);
yn = Find(1, kn, post[i][1]);
Add(xn, yn, i, 1);
}
query(1, kn, 1);
printf("%d\n", ans);
}
return 0;
}
poj 2528 经典线段树入门
最新推荐文章于 2019-11-23 10:42:02 发布