線段樹練習題二
題目
桌子上零散地放着若干個不同顏色的盒子,桌子的後方是一堵牆。如右圖所示。問從桌子前方可以看到多少個盒子?假設人站得足夠遠(輸入時,由底向上,從左到右)。
輸入樣例
16//桌子長度
5//盒子數量
4 7
12 14
1 5
6 10
11 16
輸入樣例
4
數據範圍
1<=n<=100000,1<=m<=100000,保證座標範圍爲[1,n].
解題思路
其實這道題就是一道線段樹,先把每個盒子的起始點和終點都先插入到樹中,然後用來定義每個盒子的顏色,然後看是否有覆蓋的顏色,然後統計樹即可.
程序如下
#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;
}