贪心

求最大团包含的点数,题目没有别的线索,直接变换式子观察。

$$|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;
}
最后修改:2024 年 11 月 26 日
如果觉得我的文章对你有用,请随意赞赏