坐标轴上有n个点,每个点有一个权值。第i个点的坐标是 xi ,权值是 wi 。现在对这些点建图。对于点对 (i,j) ,如果 |xi−xj|≥wi+wj ,那么就给第i个点和第j个点之间连一条边。
问建好的图中最大团有几个点。
样例解释:
Input
单组测试数据。
第一行有一个整数n (1≤n≤200000),表示坐标轴上有n个点。
接下来n行,每一行有两个整数xi, wi (0≤xi≤10^9,1≤wi≤10^9),表示第i个点的坐标和权值。
所有的xi是不一样的。
Output
输出一个整数,表示最大团中有几个点。
Input示例
样例输入1
4
2 3
3 1
6 1
0 2
Output示例
样例输出1
3
题解
把一个点拆成[xi-wi,xi+wi],把这个看成一条线段,容易发现两个点能连边为这两条线段没有交点,问题就转换成了经典的线段覆盖问题。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<set>
#include<ctime>
#include<vector>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#define mod 20101009
#define ll long long
#define N 10000005
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct node{int l,r;}a[200005];
int n;
bool cmp(node a,node b){return a.r<b.r;}
int main()
{
n=read();
for (int i=1;i<=n;i++)
{
int x=read(),w=read();
a[i].l=x-w;a[i].r=x+w;
}
sort(a+1,a+n+1,cmp);
int mn=a[1].r,ans=1;
for (int i=2;i<=n;i++)
if (a[i].l>=mn) ans++,mn=a[i].r;
printf("%d",ans);
return 0;
}