离散化 + 扫描线 + 用线段树维护, 核心是扫描线的思想
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
struct Line
{
int x1, x2, h, flag;
bool operator < (const Line &p) const{
return h < p.h;
}
}P[N];
vector<int>vec;
int n, k;
struct Segment
{
int l, r, ans, lazy;
}t[N<<2];
void Build(int p, int l, int r)
{
t[p].l = l;t[p].r = r;
if(l==r){
t[p].ans=t[p].lazy=0;
return ;
}
int mid = (l + r) >> 1;
Build(p<<1,l,mid);
Build(p<<1|1,mid+1,r);
t[p].ans = max(t[p<<1].ans,t[p<<1|1].ans);
t[p].lazy = 0;
}
void push_down(int p)
{
if(t[p].lazy){
t[p<<1].ans += t[p].lazy;
t[p<<1|1].ans += t[p].lazy;
t[p<<1].lazy += t[p].lazy;
t[p<<1|1].lazy += t[p].lazy;
t[p].lazy = 0;
}
}
void Update(int p, int L, int R, int C)
{
int l = t[p].l, r = t[p].r;
if(L <= l && r <= R){
t[p].ans += C;
t[p].lazy += C;
return ;
}
push_down(p);
int mid = (l + r) >> 1;
if(L<=mid)Update(p<<1, L, R, C);
if(mid<R)Update(p<<1|1, L, R, C);
t[p].ans=max(t[p<<1].ans, t[p<<1|1].ans);
}
int query(int p, int L, int R)
{
int l = t[p].l, r = t[p].r;
if(L <= l && r <= R){
return t[p].ans;
}
push_down(p);
int mid = (l + r) >> 1,ans = 0;
if(L <= mid)ans = max(ans, query(p<<1,L,R));
if(mid < R)ans = max(ans, query(p<<1|1,L,R));
return ans;
}
int main()
{
scanf("%d%d",&n,&k);int cnt = 0;
for(int i = 1;i <= n; i++){
int a,b;scanf("%d%d",&a,&b);
P[++cnt] = (Line){a - k, a, b - k, 1};
P[++cnt] = (Line){a - k, a, b + 1, -1};
vec.push_back(a - k);
vec.push_back(a);
}
sort(vec.begin(),vec.end());
int m=unique(vec.begin(),vec.end()) - vec.begin();
n <<= 1;Build(1, 1, n);
sort(P+1,P+n+1);int ans = 0;
for(int i = 1;i <= n; i++){
int L = lower_bound(vec.begin(),vec.end(),P[i].x1) - vec.begin();
int R = lower_bound(vec.begin(),vec.end(),P[i].x2) - vec.begin();
Update(1, L, R, P[i].flag);
ans = max(ans, t[1].ans);
}
printf("%d\n",ans);
return 0;
}
/*
4 2
1 1
3 1
3 4
2 2
*/