• BZOJ3262 陌上花开 [CDQ分治, 三位偏序]


    陌上花开

    题目描述见链接 .


    color{red}{正解部分}

    这是一道三维偏序模板题 .

    流程
    1. 开始时以 xx 为第一关键字排序, yy 为第二关键字, zz 为第三关键字排序 .
    2. yy 为关键字进行归并 .
    3. 假设现在归并的指针为 t1,t2t1, t2, 分别指向左区间和右区间, 当 A[t1].yA[t2].yA[t1].y le A[t2].y 时, 不断将 t1t1 往后移动, 且将 A[t1]A[t1] 加入以 zz 为下标的 树状数组 中 .
      否则统计 A[t2]A[t2] 的答案, 直接在 树状数组 中查询小于等于 A[t2].zA[t2].z 的个数即可 .

    排序解决 xx 偏序, 归并解决 yy 偏序, 树状数组解决 zz 偏序 .


    color{red}{实现部分}

    • 每次归并都要撤销树状数组的操作来清空树状数组 .
    • 当两个花一模一样时需要统一取其中较大的答案 (前提是刚开始的排序要保证三个关键字都得到照顾) .
    #include<bits/stdc++.h>
    #define reg register
    
    const int maxn = 100005;
    
    int N;
    int K;
    int Ans[maxn];
    int cnt[maxn];
    
    struct Node{ int x, y, z, res; } A[maxn], tmp[maxn];
    
    bool cmp(Node a, Node b){ if(a.x == b.x){ if(a.y == b.y) return a.z < b.z; return a.y < b.y; } return a.x < b.x; }
    
    struct Bit_t{
            int v[maxn<<1];
            void Add(int k, int x){ while(k<=K)v[k]+=x,k+=k&-k; }
            int Query(int k){ int s=0; while(k)s+=v[k],k-=k&-k; return s; }
    } bit_t;
    
    void merge_sort(int l, int r){
            if(l >= r) return ;
            int mid = l+r >> 1;
            merge_sort(l, mid), merge_sort(mid+1, r);
            int t1 = l, t2 = mid+1, t3 = l;
            while(t1 <= mid && t2 <= r)
                    if(A[t1].y <= A[t2].y) bit_t.Add(A[t1].z, 1), tmp[t3 ++] = A[t1 ++];
                    else A[t2].res += bit_t.Query(A[t2].z), tmp[t3 ++] = A[t2 ++];
            while(t2 <= r) A[t2].res += bit_t.Query(A[t2].z), tmp[t3 ++] = A[t2 ++];
            for(reg int i = l; i < t1; i ++) bit_t.Add(A[i].z, -1);
            while(t1 <= mid) tmp[t3 ++] = A[t1 ++];
            for(reg int i = l; i <= r; i ++) A[i] = tmp[i];
    }
    
    int main(){
            scanf("%d%d", &N, &K);
            for(reg int i = 1; i <= N; i ++) scanf("%d%d%d", &A[i].x, &A[i].y, &A[i].z);
            std::sort(A+1, A+N+1, cmp);
            merge_sort(1, N);
            for(reg int i = N; i >= 1; i --){
                    if(A[i].x == A[i+1].x && A[i].y == A[i+1].y && A[i].z == A[i+1].z) A[i].res = A[i+1].res;
                    cnt[A[i].res] ++;
            }
            for(reg int i = 0; i < N; i ++) printf("%d
    ", cnt[i]);
            return 0;
    }
    
  • 相关阅读:
    linux下yum无法使用
    判断某个网卡是否是dhcp获取的ip
    个人作业---词频统计
    第四周读书笔记
    设计关键词
    好文收藏
    Apritag角点代码检测
    处理txt文件,保存为yml和cal文件
    欧拉角欧拉矩阵
    Mysql笔记01-安装和SQL基础
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822496.html
Copyright © 2020-2023  润新知