题目地址:http://acm.pku.edu.cn/JudgeOnline/problem?id=2528
因为实现的线段树的元线段是一个左闭右开区间,题目中输入的线段需要做一下处理,我通过将右端点加1,就可以和线段树对应了。
接下来是离散化,去重点。
线段树中增加一个color域,初始值为0,-1表示当前点表示的线段有多个颜色,大于0表示单一颜色。
插入线段时先判断插入线段颜色是否和当前线段相同,不同则插入,
如果完全覆盖当前线段,把color域设置为插入线段颜色,并return.否则把其左右儿子color设置为当前节点color,把当前节点color设置为-1.
递归插入。
在统计的时候 只要统计到一个节点color域大于0就把标志数组的第color设为true,并返回,不用再继续递归统计下去,因为其子节点都被覆盖。
最后遍历标记数组统计为true的个数,即颜色数。
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 20010;
struct line
{
int l;
int r;
};
line a[MAXN];
struct node
{
int l;
int r;
int mid;
int color;
};
node seg_tree[MAXN*4];
bool flag[MAXN];
int hash[MAXN*2];
void make(int l,int r,int num)
{
seg_tree[num].l = l;
seg_tree[num].r = r;
seg_tree[num].mid = (l+r)/2;
seg_tree[num].color = 0;
if (l+1!=r)
{
make(l,seg_tree[num].mid,num*2);
make(seg_tree[num].mid,r,num*2+1);
return;
}
}
void insert(int num,int l,int r,int c)
{
// printf("test\n");
if (seg_tree[num].color!=c)
{
if (seg_tree[num].l==l&&seg_tree[num].r==r)
{
seg_tree[num].color = c;
return;
}
if (seg_tree[num].color>=0)
{
seg_tree[2*num].color = seg_tree[num].color;
seg_tree[2*num+1].color = seg_tree[num].color;
seg_tree[num].color = -1;
}
if(r<=seg_tree[num].mid)
{
insert(2*num,l,r,c);
}
else if(l>=seg_tree[num].mid)
{
insert(2*num+1,l,r,c);
}
else
{
insert(2*num,l,seg_tree[num].mid,c);
insert(2*num+1,seg_tree[num].mid,r,c);
}
}
}
void cal(int num)
{
if(seg_tree[num].color>0)
{
flag[seg_tree[num].color] = true;
return;
}
if(seg_tree[num].l+1!=seg_tree[num].r)
{
cal(2*num);
cal(2*num+1);
}
}
inline int b_search(int l,int r,int val)
{
while(l<=r)
{
int mid = (l+r)>>1;
if(hash[mid]==val)return mid;
else if(hash[mid]>val)r=mid-1;
else l = mid +1;
}
return -1;
}
int main()
{
int T,n;
scanf("%d",&T);
while (T--)
{
memset(flag,false,sizeof(flag));
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].l,&a[i].r);
a[i].r++;
hash[2*i-1] = a[i].l;
hash[2*i] = a[i].r;
}
sort(hash+1,hash+1+2*n);
int index = 2;
for(int i=1;i<2*n;i++)
{
if(hash[i]!=hash[i+1])
{
hash[index++] = hash[i+1];
}
}
make(1,index-1,1);
for(int i=1;i<=n;i++)
{
// printf("test a %d b %d\n",b_search(1,index-1,a[i].l),b_search(1,index-1,a[i].r));
insert(1,b_search(1,index-1,a[i].l),b_search(1,index-1,a[i].r),i);
}
cal(1);
int ans = 0;
for(int i=0;i<MAXN;i++)
{
if(flag[i])
{
//printf("c %d\n",i);
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 20010;
struct line
{
int l;
int r;
};
line a[MAXN];
struct node
{
int l;
int r;
int mid;
int color;
};
node seg_tree[MAXN*4];
bool flag[MAXN];
int hash[MAXN*2];
void make(int l,int r,int num)
{
seg_tree[num].l = l;
seg_tree[num].r = r;
seg_tree[num].mid = (l+r)/2;
seg_tree[num].color = 0;
if (l+1!=r)
{
make(l,seg_tree[num].mid,num*2);
make(seg_tree[num].mid,r,num*2+1);
return;
}
}
void insert(int num,int l,int r,int c)
{
// printf("test\n");
if (seg_tree[num].color!=c)
{
if (seg_tree[num].l==l&&seg_tree[num].r==r)
{
seg_tree[num].color = c;
return;
}
if (seg_tree[num].color>=0)
{
seg_tree[2*num].color = seg_tree[num].color;
seg_tree[2*num+1].color = seg_tree[num].color;
seg_tree[num].color = -1;
}
if(r<=seg_tree[num].mid)
{
insert(2*num,l,r,c);
}
else if(l>=seg_tree[num].mid)
{
insert(2*num+1,l,r,c);
}
else
{
insert(2*num,l,seg_tree[num].mid,c);
insert(2*num+1,seg_tree[num].mid,r,c);
}
}
}
void cal(int num)
{
if(seg_tree[num].color>0)
{
flag[seg_tree[num].color] = true;
return;
}
if(seg_tree[num].l+1!=seg_tree[num].r)
{
cal(2*num);
cal(2*num+1);
}
}
inline int b_search(int l,int r,int val)
{
while(l<=r)
{
int mid = (l+r)>>1;
if(hash[mid]==val)return mid;
else if(hash[mid]>val)r=mid-1;
else l = mid +1;
}
return -1;
}
int main()
{
int T,n;
scanf("%d",&T);
while (T--)
{
memset(flag,false,sizeof(flag));
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].l,&a[i].r);
a[i].r++;
hash[2*i-1] = a[i].l;
hash[2*i] = a[i].r;
}
sort(hash+1,hash+1+2*n);
int index = 2;
for(int i=1;i<2*n;i++)
{
if(hash[i]!=hash[i+1])
{
hash[index++] = hash[i+1];
}
}
make(1,index-1,1);
for(int i=1;i<=n;i++)
{
// printf("test a %d b %d\n",b_search(1,index-1,a[i].l),b_search(1,index-1,a[i].r));
insert(1,b_search(1,index-1,a[i].l),b_search(1,index-1,a[i].r),i);
}
cal(1);
int ans = 0;
for(int i=0;i<MAXN;i++)
{
if(flag[i])
{
//printf("c %d\n",i);
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}