#include <bits/stdc++.h>
using namespace std;
#define int long long

struct u {
    int l, r;
};

bool cmp(u x, u y) {
    if (x.r != y.r) return x.r < y.r;
    return x.l < y.l;
}

bool cmp2(u x, u y) {
    if (x.l != y.l) return x.l < y.l;
    return x.r > y.r;
}

signed main() {
    int n, k;
    cin >> n >> k;
    vector<u> ans(n);
    for (int i = 0; i < n; i++) {
        cin >> ans[i].l >> ans[i].r;
    }
    
    // 情况1:按右端点排序,枚举L = 右端点
    sort(ans.begin(), ans.end(), cmp);
    priority_queue<int, vector<int>, greater<int>> q1;
    int biao1 = 0;
    int maxw1 = 0;
    
    for (int id = 0; id < n; id++) {
        int window_right = ans[id].r + k;
        while (!q1.empty() && q1.top() < ans[id].r) q1.pop();
        while (biao1 < n && ans[biao1].l <= window_right) {
            q1.push(ans[biao1].r);
            biao1++;
        }
        maxw1 = max(maxw1, (int)q1.size());//q.size()用int存储之后再比较
    }
    
    // 情况2:按左端点排序,枚举L = 左端点
    sort(ans.begin(), ans.end(), cmp2);
    priority_queue<int, vector<int>, greater<int>> q2;
    int biao2 = 0;
    int maxw2 = 0;
    
    for (int id = 0; id < n; id++) {
        int window_left = ans[id].l - k;
        // 这里窗口左边界是 ans[id].l,需要删除右端点 < ans[id].l 的区间
        while (!q2.empty() && q2.top() < window_left) q2.pop();
        // 加入所有左端点 <= window_right 的区间(这里左端点就是 ans[biao2].l,已经有序)
        while (biao2 < n && ans[biao2].l <= ans[id].l) {
            q2.push(ans[biao2].r);
            biao2++;
        }
        maxw2 = max(maxw2, (int)q2.size());
    }
    
    cout << max(maxw1, maxw2) << endl;
    
    return 0;
}

这个题本质上是扫面线,但我是用堆来实现的这个扫描。

该说不说这个题用堆来做,确确实实有很多要注意的小细节。
第一个需要注意的是贪心.
    首先我们看区间大小,0到1e9,不可能枚举暴力做,接下来我们去看n的范围0到2e5可以接受,我们深思之下,会想到枚举所有所给区间的右端点来作为所选区间的起点,
为何如此,因为要取得最好的结果,我们尽量得让区间延申出去,例如一个区间[1,5],如果所给k为2,那么可以选择[1,3],[2,4],[3,5]....,最佳情况肯定是[5,7]因为这时候卡在相交的边缘,做到了尽量让区间延申出去,可能会有这样的疑惑,如果所给区间[1,5],[2,3],[3,4]屯在一块这时候好像不能延申,其实并不正确延申是通用的,我们只需要对r从小到大排序就可以了,这样的话对于每一个从小到大的r我们都尽量往外延申,则可以达到最优解
    这个过程需要用堆来实现,堆是最小堆,维护的是区间的右端点值,维护该值主要是为了,弹出过期元素。
    因为每个元素顶多出队入队一次,时间复杂度o(nlogn)
   如果仅仅想到这里,你会发现你只能对75%的样例,那另外错哪里了,很简单你同时也应该每个区间左端点来作为所选区间的终点,这时候同样也满足区间尽量向外申的根本目的,所以他也可能产生最优解,所以要做两遍扫描线
   问题就解决了
但别忘了,在排序的时候,如果初步按r从小到大排序,则相同r,l应该按从小到大排序,这样你会先遍历到l小的,如果l小的不满足就可以break了,如果l从大到小 l不满足跳过逻辑就不对了,因为小的l可能满足
但是先按从小到大排序则不需要关注这个问题,大家可以想想为什么嘻嘻嘻