cf 12D Ball - CDQ分治

传送门
每个人有3个属性,如果有人的3个属性都比自己大,那么自己就会跳楼。
求跳楼的人的个数。

以前CDQ一般是求属性小于等于自己的个数,现在变成求有没有人的属性比自己大。
你没有办法直接求出比自己小的人有哪些的,因为用的是树状数组维护个数。
那么转换下就是对于每一个人求大于自己的人的个数,把所有的权值变成负数,那么就转换回CDQ套路了。

但是还有个问题就是第一个属性排序,第二个属性归并排序,第三个属性树状数组。
第二维和第三维都是可以控制找到小于自己的个数,如果说第一个维度相同,另外两个维度满足,也会算进答案了。

所以有一个方法就是,对于每一个第一维度相同的,再进行一次CDQ,把多于的值减去即可。分段求下CDQ

时间复杂度\(O(nlog^2n)\)

老规矩,树状数组维护的那一维度要离散化。

#include <bits/stdc++.h>
#define ll long long
#define CASE int Kase = 0; cin >> Kase; for(int kase = 1; kase <= Kase; kase++)
using namespace std;
template<typename T = long long> inline T read() {
    T s = 0, f = 1; char ch = getchar();
    while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
    while(isdigit(ch)) {s = (s << 3) + (s << 1) + ch - 48; ch = getchar();} 
    return s * f;
}
const int N = 5e5 + 5, M = 1e6 + 5, MOD = 1e9 + 7, CM = 998244353, INF = 0x3f3f3f3f;
struct Lady{
    int beauty, intellect, richness, id;
    bool operator < (const Lady &b) const {
        if(beauty == b.beauty && intellect == b.intellect) return richness < b.richness;
        return beauty ^ b.beauty ? beauty < b.beauty : intellect < b.intellect;
    }
} lady[N], tmp[N];
struct BIT{
    int c[N];
    int lowbit(int x) {return x & (-x);}
    void add(int pos, int val) {for(; pos < N; pos += lowbit(pos)) c[pos] += val;}
    int sum(int pos) { int res = 0; for(; pos; pos -= lowbit(pos)) res += c[pos]; return res;}
} bit;
int b[N], ans[N];
void CDQ(int l, int r, int op){
    if(l == r) return;
    int mid = (l + r) >> 1;
    CDQ(l, mid, op), CDQ(mid + 1, r, op);
    int lp = l, rp = mid + 1, pos = l;
    while(lp <= mid && rp <= r) {
        if(lady[lp].intellect < lady[rp].intellect) bit.add(lady[lp].richness, 1), tmp[pos++] = lady[lp++];
        else ans[lady[rp].id] += op * bit.sum(lady[rp].richness - 1), tmp[pos++] = lady[rp++];
    }
    while(lp <= mid) bit.add(lady[lp].richness, 1), tmp[pos++] = lady[lp++];
    while(rp <= r) ans[lady[rp].id] += op * bit.sum(lady[rp].richness - 1), tmp[pos++] = lady[rp++];
    for(int i = l; i <= mid; i++) bit.add(lady[i].richness, -1);
    for(int i = l; i <= r; i++) lady[i] = tmp[i]; 
}
int main(){
    int n = read();
    for(int i = 1; i <= n; i++) lady[i].beauty = -read();
    for(int i = 1; i <= n; i++) lady[i].intellect = -read();
    for(int i = 1; i <= n; i++) lady[i].richness = -read(), lady[i].id = i, b[i] = lady[i].richness;
    sort(b + 1, b + n + 1);
    int q = unique(b + 1, b + n + 1) - b - 1;
    for(int i = 1; i <= n; i++) {
        lady[i].richness = lower_bound(b + 1, b + q + 1, lady[i].richness) - b;
    }
    sort(lady + 1, lady + n + 1);
    CDQ(1, n, 1);
    sort(lady + 1, lady + n + 1);
    for(int i = 1; i <= n; i++) {
        int j = i + 1;
        for(; j <= n; j++) if(lady[i].beauty != lady[j].beauty) break;
        CDQ(i, j - 1, -1);
        i = j - 1;
    }
    int res = 0;
    for(int i = 1; i <= n; i++) {
        res += ans[i] ? 1 : 0;
    }
    printf("%d\n", res);
    return 0;
}
posted @ 2021-02-03 16:32  Emcikem  阅读(76)  评论(0编辑  收藏  举报