1 条题解

  • 0
    @ 2026-10-26 20:16:52

    思路与算法

    先按地位升序分组,同地位全部加入年龄Fenwick后,算每个人作队长时能容纳的人数C_i。对查询x,y,队长地位至少max(r_x,r_y),年龄必须落在[max(a_x,a_y)-K,min(a_x,a_y)+K]。把查询按地位门槛降序,加入满足门槛的队长,用年龄线段树取C_i最大值。

    正确性说明

    固定队长时,所有地位不高于他且年龄差不超过K的人都可加入,互相没有额外限制,因此C_i就是最大小组大小。查询的地位与年龄条件准确刻画同时包含x,y的全部队长。离线激活不遗漏也不引入不合格队长,区间最大值给出最优人数。

    复杂度

    年龄离散化和两次排序O((n+q)log(n+q)),Fenwick与线段树操作O((n+q)logn),初始化O(n),空间O(n+q)。

    易错点

    同地位允许并列最高,计算C_i前必须整组加入。年龄窗口为闭区间;两年龄相差超过2K时队长区间为空,输出-1。区间端点运算使用64位。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    struct Fen {
        vector<int> f;
        Fen(int n) : f(n + 1) {
        }
        void add(int x) {
            for (x++; x < (int)f.size(); x += x & -x)
                f[x]++;
        }
        int sum(int x) {
            int s = 0;
            for (; x; x -= x & -x)
                s += f[x];
            return s;
        }
    };
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        long long K;
        cin >> n >> K;
        vector<long long> r(n), a(n), xs;
        for (auto &x : r)
            cin >> x;
        for (auto &x : a)
            cin >> x;
        xs = a;
        sort(xs.begin(), xs.end());
        xs.erase(unique(xs.begin(), xs.end()), xs.end());
        int S = 1;
        while (S < (int)xs.size())
            S *= 2;
        auto lo = [&](long long x) {
            return lower_bound(xs.begin(), xs.end(), x) - xs.begin();
        };
        auto hi = [&](long long x) {
            return upper_bound(xs.begin(), xs.end(), x) - xs.begin();
        };
        vector<int> ord(n), sz(n);
        iota(ord.begin(), ord.end(), 0);
        sort(ord.begin(), ord.end(), [&](int x, int y) {
            return r[x] < r[y];
        });
        Fen f(xs.size());
        for (int i = 0, j; i < n; i = j) {
            j = i;
            while (j < n && r[ord[j]] == r[ord[i]])
                f.add(lo(a[ord[j++]]));
            for (int t = i; t < j; t++) {
                int x = ord[t];
                sz[x] = f.sum(hi(a[x] + K)) - f.sum(lo(a[x] - K));
            }
        }
        int q;
        cin >> q;
        struct Q {
            long long r, l, h;
            int id;
        };
        vector<Q> qs(q);
        for (int i = 0, x, y; i < q; i++) {
            cin >> x >> y;
            --x;
            --y;
            qs[i] = {max(r[x], r[y]), max(a[x], a[y]) - K, min(a[x], a[y]) + K, i};
        }
        sort(qs.begin(), qs.end(), [](Q x, Q y) {
            return x.r > y.r;
        });
        vector<int> tr(2 * S, -1), ans(q);
        int pos = n - 1;
        for (auto qu : qs) {
            while (pos >= 0 && r[ord[pos]] >= qu.r) {
                int x = ord[pos--], i = S + lo(a[x]);
                tr[i] = max(tr[i], sz[x]);
                for (i /= 2; i; i /= 2)
                    tr[i] = max(tr[2 * i], tr[2 * i + 1]);
            }
            int z = -1;
            for (int l = S + lo(qu.l), h = S + hi(qu.h); l < h; l /= 2, h /= 2) {
                if (l & 1)
                    z = max(z, tr[l++]);
                if (h & 1)
                    z = max(z, tr[--h]);
            }
            ans[qu.id] = z;
        }
        for (int z : ans)
            cout << z << '\n';
    }
    
    • 1