线段树练习题一

Description

桌子上零散地放着若干个盒子,桌子的后方是一堵墙。如右图所示。现在从桌子的前方射来一束平行光, 把盒子的影子投射到了墙上。问影子的总宽度是多少?

Sample Input

20 //桌面总宽度
4 //盒子数量
1 5
3 8
7 10
13 19

Sample Output

15

Hint

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

题目分析

这道题目是一个经典的离散化模型。在这里,我们略去某些处理的步骤,直接分析重点问题,可以把题目抽象地描述如下:x轴上有若干条线段,求线段覆盖的总长度

解题思路

基本思想:先把所有端点坐标从小到大排序,
将坐标值与其序号一一对应。这样便可以将原先的坐标值转化为序号后,对其应用前一种算法,再将最后结果转化回来得解。该方法对于线段数相对较少的情况有效,时间复杂度(n^2)

b [10000,20000]   [30000,50000]   [40000,60000]   [50000,60000]
a排序得100002000030000400005000050000,60000,60000
对应得 1       2      3       4     5      6     7     8
[1,2]              [3,5]                    [4,7]                   [6,8]

AC代码

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,s,a[200005],b[100005][3];
int main()
{
   
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
   
		scanf("%d%d",&a[2*i-1],&a[2*i]);
		b[i][1]=a[2*i-1];//离散化
		b[i][2]=a[2*i];
	}
	sort(a+1,a+1+2*m);	//排序
	for(int i=2;i<=2*m;i++)
  	 for(int j=1;j<=m;j++)
      if(b[j][1]<a[i]&&a[i]<=b[j][2])//如果覆盖
        {
   
           s+=a[i]-a[i-1];//累加区间的值
           break;
        }
    printf("%d",s);    
} 

谢谢