1 条题解
-
0
思路与算法
先按地位升序分组,同地位全部加入年龄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