笔记
思路一
一个长度为L,全部为0的数列。现在统计各个点被覆盖的次数,每个点被覆盖一次就加1,最后找数列里为0的点即可。 实现:利用差分数组维护区间加1的操作
#include<bits/stdc++.h>
using namespace std;
int l,m;
int delta[10010];
int main()
{
scanf("%d%d", &l, &m);
for (int i = 1; i<= m; i++)
{
int x, y;
scanf("%d%d", &x, &y);
if (x > y) swap(x, y);
delta[x]++;
delta[y+1]--;
}
int a = 0, cnt = 0;
for (int i = 0; i <= l; i++)
{
a += delta[i];
if (a == 0) cnt++;
}
cout << cnt;
}
思路二
有交集的区间可以合并成一个大区间,汇总成几个互不相交的长区间。区间长度即为挖走的树的个数。
只需要把区间按左界排序,判断它的右界和下一个区间的左界的位置关系。右界取两个区间最大的那个
(特殊情况:第二个区间完全在第一个区间里面)
#include<bits/stdc++.h>
using namespace std;
int l,m;
struct ty
{
int x, y;
}a[1000];
bool comp(ty a, ty b)
{
if (a.x < b.x) return 1;
return 0;
}
int main()
{
scanf("%d%d", &l, &m);
for (int i = 1; i<= m; i++)
{
scanf("%d%d", &a[i].x, &a[i].y);
}
sort (a+1, a+1+m, comp);
int cnt = l+1;
int l = a[1].x, r = a[1].y;
for(int i = 2; i <= m; i++)
{
if (a[i].x < r)
{
r = max(r, a[i].y);
}
else{
cnt -= (r-l+1);
l = a[i].x, r = a[i].y;
}
}
cnt -= (r-l+1);
cout << cnt;
}
思路三
离散化
给端点值做标记,开始挖树的点标记值+1,结束的点-1
#include<bits/stdc++.h>
using namespace std;
int l,m;
struct ty
{
int pos, num;
}delta[1000];
bool comp(ty a, ty b)
{
if (a.pos == b.pos) return a.num < b.num;
return a.pos < b.pos;
}
int main()
{
scanf("%d%d", &l, &m);
for (int i = 1; i<= m; i++)
{
int x, y;
scanf("%d%d", &x, &y);
delta[i].pos = x;
delta[i].num = +1;
delta[i+m].pos = y+1;
delta[i+m].num = -1;
}
sort (delta+1, delta+1+2*m, comp);
int cnt = 0;
int a = 0;
for(int i = 1; i <= 2*m; i++)
{
a = a + delta[i].num;
if (a == 1 && delta[i].num == 1)
cnt += delta[i].pos - delta[i-1].pos;
}
cnt += l - delta[2*m].pos+1;
cout << cnt;
}

京公网安备 11010502036488号