题目大意:
与线段树练习1差不多,只不过是求看到的盒子的数量(被挡住的盒子不算,假设人的视线就是那道平行光)
解题思路:
线段树
给每个盒子染上不同的颜色,最后统计除了0之外能看到的颜色有多少种就可以了。
cover=-1 表示该区间有多种颜色的盒子
cover>=0 表示该区间只有 cover 单种颜色
源程序:
#include<cstdio>
using namespace std;
struct node{
int cover;
}a[400001];
int x1,y1,l,n;
bool f[100001];
void insert(int i,int l,int r,int b,int e,int color)//l,r表示当前区间,b,e表示要染色的区间
{
if (a[i].cover!=color)
{
int mid=(l+r)/2;
if (l==b&&r==e) a[i].cover=color;
//如果就是这个区间,则可以直接涂,覆盖掉本来的颜色
else
{
if (a[i].cover>=0)
//如果已经有一种颜色,则再加入颜色就表示有多种颜色
{
a[i*2].cover=a[i].cover;
a[i*2+1].cover=a[i].cover;
a[i].cover=-1;
}
if (e<=mid) insert(i*2,l,mid,b,e,color);
else if (b>=mid) insert(i*2+1,mid,r,b,e,color);
else {
insert(i*2,l,mid,b,mid,color);
insert(i*2+1,mid,r,mid,e,color);
}//后面的和线段树练习1差不多
}
}
}
void count_answer(int i,int l,int r)
{
int mid=(l+r)/2;
if (a[i].cover>=0) f[a[i].cover]=1;
else if (r-l>1) //否则这个区间有多种颜色,并且
//这个区间表示的范围大于1
//则说明有多种颜色,往下统计
{
count_answer(i*2,l,mid);
count_answer(i*2+1,mid,r);
}//f是一个桶,f[i]=1表示这个盒子可以看到
//f[i]=0表示这个盒子看不到
}
int main()
{
scanf("%d",&l);
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d",&x1,&y1);
insert(1,1,l,x1,y1,i);
}
count_answer(1,1,l);
int ans=0;
for (int i=1;i<=n;i++) if (f[i]) ans++;
printf("%d",ans);//统计
}