线段树练习题二
题目
桌子上零散地放着若干个不同颜色的盒子,桌子的后方是一堵墙。如右图所示。问从桌子前方可以看到多少个盒子?假设人站得足够远(输入时,由底向上,从左到右)。
输入样例
16//桌子长度
5//盒子数量
4 7
12 14
1 5
6 10
11 16
输入样例
4
数据范围
1<=n<=100000,1<=m<=100000,保证坐标范围为[1,n].
解题思路
其实这道题就是一道线段树,先把每个盒子的起始点和终点都先插入到树中,然后用 c o l o r color color来定义每个盒子的颜色,然后看是否有覆盖的颜色,然后统计树即可.
程序如下
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,x,y,ans,b[100001];
struct t
{
int l,r,colorx;
}tree[400001];
void Build(int x,int L,int R)//建树
{
tree[x].l=L; tree[x].r=R;
if(L + 1 == R) return;
int mid=(L+R)>>1;
Build(x*2,L,mid);
Build(x*2+1,mid,R);
return;
}
void Ins(int x,int L,int R,int color)//插入
{
if (tree[x].l == L && tree[x].r == R)
tree[x].colorx = color;
else
{
if (tree[x].colorx >= 0)
{
tree[x*2].colorx = tree[x].colorx;
tree[x*2+1].colorx = tree[x].colorx;
tree[x].colorx = -1;
}
int mid = (tree[x].l + tree[x].r) >> 1;
if (R <= mid) Ins (x * 2,L,R,color);
else if (L >= mid) Ins (x * 2 + 1,L,R,color);
else {
Ins (x * 2,L,mid,color);
Ins (x * 2 + 1,mid ,R,color);
}
}
}
void Count (int x)//统计
{
if (tree[x].colorx >= 0)
b[tree[x].colorx] = true;
else if(tree[x].l+1 < tree[x].r)
{
Count(x * 2);
Count(x * 2 + 1);
}
}
int main()
{
scanf("%d%d",&n,&m);
Build(1,1,n);
for (int i=1; i<=m; ++i)
{
scanf("%d%d",&x,&y);
Ins(1,x,y,i);
}
Count(1);
for(int i = 1;i <= m; ++i)
if(b[i] == true) ans++;
printf("%d",ans);
return 0;
}