1. 对于这道题有鄙人这里陈述两种解法******
  2. 第一种复杂,第二种简单,没学过并查集的同学可以看第二种。
  3. 第一种是“并查集”,这种解法有点复杂,“并查集的思想”是把相互之间有关系的元素放在不同的集合,它的思路可以区分不同的元素,而这道题对于不同的元素可以理解为,不同的区间。题目中不是说输入M行,每行两个数据吗,这两个数据其实可以看成一个区间,接下来就运用并查集的思想,把区间相互重叠的放在一个集合,注意:比如3个区间,[10,30],[20,40],[35,50],这三个区间也是一个集合的,他们虽然没有彼此之间有联系,但是你画在纸上你就发现他们还是重叠在一条线上。另外要处理一下,如果这两个区间有联系,比如A的区间为[30,50],B的区间为[40,80],那么他们就放在同一集合,而且他们的区间都要变成[30,80]。
  4. ###没学过并查集的同学,可以在百度上搜一下哦,不然看第一种解法是看不懂的,但是第一种解法它的空间和时间上都是很优的,比用数组标记啊要快很多
  5. 第二种解法很简单,这就是数组标记,这种思路在很多题是可以用的,这是一种很重要的思想,听学长说他在面试的时候用到了
  6. 这种思路在这道题是这样的,开一个数组d[ ],开始时所有值都是0,接下来,如果 i 这个位置在公路上,那么d[ i ]=1,然后统计一下d[i]==1的个数,就是要被砍掉的数的数量,那么剩下的就可以求了,或者统计d[i]==0的个数,就是剩下的树的棵数
  7. /*#include<iostream>
  8. using namespace std;
  9. #define N 1005
  10. struct node{
  11. int x;
  12. int y;
  13. int e;
  14. }f[N];
  15. int L,M;
  16. int max( int a,int b ){
  17. return a>b ? a:b;
  18. }
  19. int min( int a,int b ){
  20. return a>b ? b:a;
  21. }
  22. void Init_( ){
  23. int i,j;
  24. for(i=1;i<=M;i++){
  25. f[i].e=i;
  26. }
  27. return ;
  28. }
  29. int getf( int v ){
  30. if( f[v].e==v )
  31. return v;
  32. else{
  33. f[v].e=getf( f[v].e );
  34. return f[v].e;
  35. }
  36. }
  37. void merge_( int a,int b ){
  38. int t1,t2;
  39. t1=getf( a );
  40. t2=getf( b );
  41. if( t1!=t2 ){
  42. f[t2].e=t1;
  43. }
  44. f[t1].x=min( f[t1].x,f[t2].x );
  45. f[t1].y=max( f[t1].y,f[t2].y );
  46. f[t2].x=min( f[t1].x,f[t2].x );
  47. f[t2].y=max( f[t1].y,f[t2].y );
  48. }
  49. int ok( int a,int b,int c,int d ){ //这个函数是判断两个区间是否重叠
  50. if( c<=b&&a<=c )
  51. return 1;
  52. if( a<=d&&c<=a )
  53. return 1;
  54. return 0;
  55. }
  56. int main( ){
  57. int i,j;
  58. cin>>L>>M;
  59. for(i=1;i<=M;i++){
  60. cin>>f[i].x>>f[i].y;
  61. }
  62. Init_( );
  63. for(i=1;i<=M;i++){
  64. for(j=i+1;j<=M;j++){
  65. if( ok( f[i].x,f[i].y,f[j].x,f[j].y ) )
  66. merge_( i,j );
  67. }
  68. }
  69. long sum=0;
  70. for(i=1;i<=M;i++){
  71. if( f[i].e==i )
  72. sum+=f[i].y-f[i].x+1;
  73. }
  74. cout<<L+1-sum<<endl;
  75. return 0;
  76. }*/
  77. //############################第二种解法如下
  78. #include<iostream>
  79. using namespace std;
  80. #define N 10005
  81. int main(){
  82. int i,j,k,sum=0;
  83. int L,M,x,y;
  84. cin>>L>>M;
  85. int d[N]={0};
  86. for(i=1;i<=M;i++){
  87. cin>>x>>y;
  88. for(j=x;j<=y;j++)
  89. d[j]=1; //区间[x,y]就是公路要经过的,所以这个范围的树要被砍,所以d[i]=1
  90. }
  91. for(i=0;i<=L;i++){
  92. if( d[i]!=1)
  93. sum++;
  94. }
  95. cout<<sum<<endl;
  96. return 0;
  97. }
点赞(0)
 

6 分

2 人评分

 

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 1 条评论

wangjinbo 5年前 回复TA
没有线段树差评