对于i∈S,有xi和wi。问S的最大子集其中每对i,j满足|xi-xj|>=wi+wj
首先可以干掉绝对值。然后变形得xi-wi>=wj+xj
所以对每个点建线段[xi-wi,xi+wi]。
即对左端点xi-wi,统计比xi-wi小的右端点组成的最大子集的大小,使用树状数组维护即可,查询到的数存入右端点。
问题转化为对于每条线段[xi-wi,xi+wi],更新树状数组xi+wi,值为[1,xi-wi]最大数+1,则最后答案即为树状数组中的最大值。
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
#define FOR(i,j,k) for(i=j;i<=k;i++)
#define N 200001
int c[N * 2], v[N * 2];
int n, sz = 0;
inline int lowbit(int x) { return x & -x; }
inline int sum(int x) {
int s = 0;
for (; x >= 1; x -= lowbit(x)) s = max(c[x], s);
return s;
}
inline void update(int i, int x) {
for (; i <= sz; i += lowbit(i)) c[i] = max(c[i], x);
}
struct Ask {
int x, l, r;
friend bool operator < (const Ask &a, const Ask &b) {
return a.x < b.x;
}
} q[N];
map<int, int> hash;
int main(){
int w, i;
scanf("%d",&n);
FOR(i,1,n) {
scanf("%d%d", &q[i].x, &w);
q[i].l = q[i].x - w; q[i].r = q[i].x + w;
}
sort(q + 1, q + 1 + n);
FOR(i,1,m) {
if(!hash.count(q[i].l)) hash[q[i].l] = ++sz;
if(!hash.count(q[i].r)) hash[q[i].r] = ++sz;
}
FOR(i,1,n) update(hash[q[i].r], sum(hash[q[i].l]) + 1);
printf("%d\n", sum(sz));
return 0;
}