题解 UVA1617 【笔记本 Laptop】
分析
首先,我们发现每个 和 都是绑在一起的,于是就可以想到用 struct 结构体来存储每个区间的左右端点。
struct asdf
{
int r,d;
}a[N];
既然要让空隙尽可能少,那么就意味着我们要尽量连接每个线段,也就是贪心,我们可以从左到右依次试着连接,为了能更好地连接右一个线段,我们得把当前放的线段尽量往右放,第一次放的线段放那个区间最右边,所以我们把这些区间按右端点从左到右排序,如果右端点一样,就按左端点从左到右排序。
bool cmp(asdf x,asdf y)
{
return x.d<y.d||(x.d==y.d&&x.r<y.r);
//按 右端点从左到右 或 右端点相等且左端点从左到右 排序
}
我们用 记录之前最靠右的线段的位置,一开始 ,即第一个区间的右端点。
接下来循环,从 开始尝试连接,我们会遇到 种情况:
第一种:,此时不管线段怎么放,都无法与 连接,所以只能放弃连接,增加空隙数,并把当前的线段放在 ,并更新 ,即 ans++;R=a[i].d。

第二种:,此时为就可以连接,为了让 尽量靠右,我们只需把线段放在 右侧,并更新 ,即 R++;,不过,有种情况需要特判,若此时 正好等于 ,那么就不能放右边,我们可以选择放左边,所以需要特判一下。

几个小误区
不可能出现 的情况,因为我们已经将右端点排序,上次选的 一定是 。
题目中说“,当且仅当 ”,这意味着左端点较左的右端点也较左,也就是说不包含以下这种情况:

代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int T,n,ans,R;
struct asdf
{
int r,d;
}a[N];
bool cmp(asdf x,asdf y)
{
return x.d<y.d||(x.d==y.d&&x.r<y.r);
//按 右端点从小到大 或 右端点相等且左端点从小到大 排序
}
int main()
{
cin>>T;
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].r>>a[i].d;
}
sort(a+1,a+n+1,cmp);
ans=0;
R=a[1].d;//第一次取第一个区间右端点
for(int i=2;i<=n;i++)
{
if(R<a[i].r)//第一种
{
ans++;
R=a[i].d;
}
else if(R!=a[i].d)//第二种 别忘了排除R==a[i].d
{
R++;
}
}
cout<<ans<<endl;
}
return 0;
}

浙公网安备 33010602011771号