贪心
求最大团包含的点数,题目没有别的线索,直接变换式子观察。
$$|x_i - x_j| \geq w_i + w_j$$
钦定 $x_i > x_j$ 拆掉绝对值,如果 $x_i < x_j$ 的话交换 $i,j$ 就一样了。
$$x_i - x_j \geq w_i + w_j$$
$$x_i - w_i \geq x_j + w_j$$
所以节点 $i,j(x_i > x_j)$ 连边当且仅当 $x_i - w_i \geq x_j + w_j$,式子左边只与 $i$ 有关,右边只与 $j$ 有关。令 $l_i = x_i - w_i,r_i = x_i + w_i$,那么 $i,j$ 连边当且仅当 $[l_i,r_i) \cap [l_j,r_j) = \varnothing$,如果两条线段有交,它们就不会连边。
问题转化为在给定的 $n$ 条线段中选择若干条线段,满足线段两两无交,最大化选择的线段数量。经典贪心问题,将所有线段按照右端点排序后贪心选择即可。
时间复杂度 $O(n \log n)$。
#include<bits/stdc++.h>
using namespace std;
vector<pair<int,int>> v;
int n,ans;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
static int x,w;
scanf("%d%d",&x,&w);
v.push_back({x-w,x+w-1});
}
sort(v.begin(),v.end(),[](auto x,auto y){
return x.second<y.second;
});
int pos=INT_MIN;
for(auto [l,r]:v) if(pos<l) ++ans,pos=r;
printf("%d\n",ans);
return 0;
}