【SSL2645】线段树练习题2

Description

桌子上零散地放着若干个不同颜色的盒子,桌子的后方是一堵墙。如右图所示。问从桌子前方可以看到多少个盒子?假设人站得足够远(输入时,由底向上,从左到右)。 

Input

Output

Sample Input

16  //桌子长度
5   // 盒子数量
4 7
12 14
1 5
6 10
11 16

Sample Output


4

Hint

1<=n<=100000,1<=m<=100000,保证坐标范围为[1,n]

设-1为多种颜色,0及0以上为不同种类的颜色,然后用线段树维护

#include
#include
#include
#include
using namespace std;
struct node{
	int l,r;
	int cover;
}f[400001];
int n,m,ans[1000100];
void ins1(int x,int l,int r,int a,int b,int color){
	if(f[x].cover!=color){
		int mid=(l+r)>>1;
		if(l==a&&r==b)f[x].cover=color;
		else{
			if(f[x].cover>=0){
				f[x*2].cover=f[x*2+1].cover=f[x].cover;
				f[x].cover=-1;
			}
			if(b<=mid)ins1(x*2,l,mid,a,b,color);
			else if(a>=mid)ins1(x*2+1,mid,r,a,b,color);
			else{
				ins1(x*2,l,mid,a,mid,color);
				ins1(x*2+1,mid,r,mid,b,color);
			}
		}
	}
}
void count1(int x,int l,int r){
	int mid=(l+r)>>1;
	if(f[x].cover>=0)ans[f[x].cover]=1;
	else if(l+1<r){
		count1(x*2,l,mid);
		count1(x*2+1,mid,r);
	}
}
int main(){
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++){
    	int x,y;
    	scanf("%d%d",&x,&y);
    	ins1(1,1,m,x,y,i);
    }
    count1(1,1,m);
    int sum=0;
    for(int i=1;i<=n;i++)
    if(ans[i]==1)sum++;
    cout<<sum;
	return 0;
}

你可能感兴趣的:(题解,线段树)