AtCoder Beginner Contest 231 F - Jealous Two(二维偏序)

F - Jealous Two

题目大意:

给出 \(n\) 个点 \((a_i, b_i)\) ,问满足下列条件的 \((i, j)\) 有多少对:

  • \(1 \leq i, j \leq n\)
  • \(a_i \geq a_j\) && \(b_i \leq b_j\)
思路:

典型的二维偏序问题。

考虑类似离散化后用树状数组求逆序对的方法。那么我们要解决的问题就是如何处理等于关系。

我们以 \(b\) 作为关键字排序,然后逆序采用双指针,对于当前的下标 \(i\),将 \(b\) 相同的点加入到树状数组中(比 \(val[i].b\) 小的在之前加过了),然后我们要求有多少个点 \(val[j].a\) 满足 \(val[i].a \geq val[j].a\) ,那么就是求(离散化后)有多少个点在 \([0, val[i].a]\) 上。

for (int i = n, j = n; i >= 1; i--) {
    while (j >= 1 && val[i].b == val[j].b) {
        fen.add(getid(val[j].a, ta), 1);
        j--;
    }
    ll tmp = fen.sum(getid(val[i].a, ta));
    ans += tmp;
}

我们也可以顺序的采用双指针,对于当前的下标 \(i\),不同的是计算点的数量时,求(离散化后)有多少个点在 \([val[i].a, n]\) 上。

for (int i = 1, j = 1; i <= n; i++) {
    while (j <= n && val[j].b == val[i].b) {
        fen.add(getid(val[j].a, ta), 1);
        j++;
    }
    ll tmp = fen.rangeSum(getid(val[i].a, ta) - 1, n);
    ans += tmp;
}
Code:
template <typename T>
struct Fenwick {
    const int n;
    vector<T> a;
    Fenwick(int n) : n(n), a(n + 1) {}
    void add(int x, T v) {
        for (int i = x; i <= n; i += i & -i) {
            a[i] += v;
        }
    }
    T sum(int x) {
        T ans = 0;
        for (int i = x; i > 0; i -= i & -i) {
            ans += a[i];
        }
        return ans;
    }
    T rangeSum(int l, int r) {
        return sum(r) - sum(l);
    }
};
 
struct Node {
    int a;
    int b;
    bool operator<(const Node &t) const {
        return b < t.b;
    }
};
 
int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n;
    cin >> n;
    Fenwick<ll> fen(n);
    vector<Node> val(n + 1);
    vector<int> ta, tb;
 
    auto getid = [&](int x, vector<int> &t) {
        return lower_bound(t.begin(), t.end(), x) - t.begin() + 1;
    };
 
    for (int i = 1; i <= n; i++) {
        cin >> val[i].a;
        ta.emplace_back(val[i].a);
    }
    for (int i = 1; i <= n; i++) {
        cin >> val[i].b;
        tb.emplace_back(val[i].b);
    }
 
    sort(ta.begin(), ta.end());
    ta.erase(unique(ta.begin(), ta.end()), ta.end());
    sort(tb.begin(), tb.end());
    tb.erase(unique(tb.begin(), tb.end()), tb.end());
 
    sort(val.begin() + 1, val.end());
    ll ans = 0;
    for (int i = n, j = n; i >= 1; i--) {
        while (j >= 1 && val[i].b == val[j].b) {
            fen.add(getid(val[j].a, ta), 1);
            j--;
        }
        ll tmp = fen.sum(getid(val[i].a, ta));
        ans += tmp;
    }
    cout << ans << "\n";
    return 0;
}
posted @ 2022-03-27 15:07  Nepenthe8  阅读(69)  评论(0编辑  收藏  举报