zoukankan      html  css  js  c++  java
  • cf 12D Ball

    传送门
    每个人有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
    ", res);
        return 0;
    }
    
    I‘m Stein, welcome to my blog
  • 相关阅读:
    Activity 与ListActivity的区别
    自定义标题栏
    解决小程序无法触发SESSION问题
    js数组与字符串经常用的几种简单的方法
    python程序与进制的执行过程
    常问的 web前端 问题
    如何判断页面滑到了屏幕最底部
    http请求状态保持的四种方法
    vue知识点归纳与总结(笔记)
    Nginx常用命令及使用场景
  • 原文地址:https://www.cnblogs.com/Emcikem/p/14367748.html
Copyright © 2011-2022 走看看