第一种:暴力破解
for(i:1~M)
for(j:区间长度)
对于本题数据L(1 <= L <= 10000)和 M(1 <= M <= 100),时间复杂度最大为O(M*L),可以ac;
但如果数据范围扩大,此方法则行不通。
第二种:差分记录每个点被区域覆盖的次数,覆盖0次的点则有树。
#include<iostream>
using namespace std;
int delta[10010]; //差分:记录每一个点与前一个点上区域覆盖的次数之差,
//其值表示当前点被区域覆盖的次数
int main(){
int l; //马路的长度
int m; //区域的数目
cin >> l >> m;
for(int i = 0; i < m; i++){
int start, end;
cin >> start >> end;
if(start <= end){//当起始点 <= 终止点时
delta[start]++; //起始点比其前一个点多被覆盖一次
delta[end+1]--; //终止点的后一个点比终止点少被覆盖一次
}
else{
delta[end]++;
delta[start+1]--;
}
}
int sum = 0; //树的数目总和
int a = 0; //记录当前点被区域覆盖的次数
for(int i = 0; i <= l; i++){
a += delta[i];
if(a == 0){
sum++;
}
}
cout << sum <<endl;
return 0;
}
第三种:将各区域按起始端点从大到小进行排序,合并有交集的区域,再计算减去每块区域移走树木的数量。
#include<iostream>
#include<algorithm>
using namespace std;
struct area{
int start;
int end;
}a[110];
bool comp(area a, area b){
if(a.start < b.start)
return 1;
else
return 0;
}
int main(){
int l, m;
cin >> l >> m;
for(int i = 0; i < m; i++){
cin >> a[i].start >> a[i].end;
}
sort(a, a + m, comp); //将区域按照起始端点从左到右排序
int left = a[0].start; //记录一个区域的左端点
int right = a[0].end; //记录一个区域的右端点
int cnt = l + 1; //刚开始有l+1棵树
for(int i = 1; i < m; i++){
if(a[i].start < right){//当前区域与上一区域有交集
right = max(right, a[i].end);
}
else{//当前区域与上一区域无交集
cnt -= right - left + 1; //减去上一个连续的区域中移走的树
left = a[i].start; //更新当前区域端点值
right = a[i].end;
}
}
//考虑最后一个区域的情况
cnt -= right - left + 1;
cout << cnt << endl;
}
第四种:创建结构体,只维护端点的位置和端点的差分值,a += delta[i] 当a == 0时,i为每个不连续的区域起始点的前一个点,则 (a == 1 && delta[i] == 1) i为每个不连续的区域的起始点。由此可以计算出树的数量,记得要加上最后一个终止点到路尽头的树。#include<iostream>
#include<algorithm>
using namespace std;
struct area{
int pos; //区域端点的位置
int num; //区域端点与前一个点的差值
}delta[220];
bool comp(area a, area b){
if(a.pos < b.pos)
return 1;
else
return 0;
}
int main(){
int l, m;
cin >> l >> m;
int start, end;
for(int i = 0; i < m; i++){//维护每个端点的差分值,起始点则+1,终止点的下一个点则-1
cin >> start >> end;
delta[i].pos = start;
delta[i].num = 1;
delta[i+m].pos = end + 1;
delta[i+m].num = -1;
}
sort(delta, delta+2*m, comp); //将结构体中维护的端点从左到右排序
int a = 0; //记录当前点的状态
int cnt = 0; //记录树的数量
for(int i = 0; i < 2*m; i++){
a += delta[i].num; //
if(a == 1 && delta[i].num == 1){//当前点为区域的起始点
cnt += delta[i].pos - delta[i-1].pos; //区域起始点 - 上一个区域终止点的下一个点 = 树的数量
}
}
//考虑最后一个端点到路尽头的情况
cnt += l - delta[2*m-1].pos + 1;
cout << cnt << endl;
}

京公网安备 11010502036488号