• BZOJ3262陌上花开(三维偏序问题(CDQ分治+树状数组))+CDQ分治基本思想


    emmmm我能怎么说呢

    CDQ分治显然我没法写一篇完整的优秀的博客,因为我自己还不是很明白...

    因为这玩意的思想实在是太短了:

    fateice如是说道:

    如果说对于一道题目的离线操作,假设有n个操作

    把n个操作分成两半,可以想到的是,假如说提出上面那半的修改操作,下面那半提出询问操作

    那么这些修改操作对下面的询问操作显然是都产生了相同的影响的。

    然后对于每一半的操作都这样递归下去,然后就有了CDQ分治处理问题的基本方法

    (图片来自fateice大爷的怕怕踢)

    但是再往深处说我也不知道该怎么说,等研究的更深入了再把CDQ分治的完整博客写出来吧

    如果哪位路过的好心人看见了,记得催更

    丢一篇大佬的上古博客:https://www.cnblogs.com/mlystdcall/p/6219421.html(希望大佬不要diss我私自搬他的博客的链接)

    下面是题目:

    Description

    有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),用三个整数表示。
    现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。
    定义一朵花A比另一朵花B要美丽,当且仅Sa>=Sb,Ca>=Cb,Ma>=Mb。
    显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。
     

    Input

    第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。
    以下N行,每行三个整数si, ci, mi (1 <= si, ci, mi <= K),表示第i朵花的属性

    Output

    包含N行,分别表示评级为0...N-1的每级花的数量。

    Sample Input

    10 3
    3 3 3
    2 3 3
    2 3 1
    3 1 1
    3 1 2
    1 3 1
    1 1 2
    1 2 2
    1 3 2
    1 2 1

    Sample Output

    3
    1
    3
    0
    1
    0
    1
    0
    0
    1

    emmm读完题目后我们显然的可以想到这是三维偏序的CDQ分治的基本题

    然后就是对一维排序,对第二维CDQ分治,同时用树状数组处理第三维

    但实际上我是把这题当成学习板子的板子题写的,所以我代码基本是学习别人的...

    这题比较坑的地方是,对于属性值完全相同的花来说,各自互相美于对面,

    这就好像你和你的几个克隆体站在一起,你比你的克隆体们聪明,你的克隆体们比你的克隆体们聪明,你的克隆体们又比你聪明...

    或者说是,你把一份代码复制成数份,然后你的代码比你的代码优秀,你的代码又比你的代码优秀..

    处理方式简单讲就是先把所有属性值相同的花都记一个数量,然后当做一种花处理,最后处理评级时再给加上...

    总之具体处理过程还是看代码吧...至少代码里有注释....

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define uint unsigned int
     4 #define ull unsigned long long
     5 using namespace std;
     6 const int maxn = 100010;
     7 struct Query {
     8     int s, c, m;
     9     int num, sum;
    10     bool operator < (const Query &A) const {
    11         return c == A.c ? m < A.m : c < A.c;
    12     }
    13     bool operator != (const Query &A) const {
    14         return s != A.s || c != A.c || m != A.m;
    15     }
    16 }a[maxn], q[maxn];
    17 int n, k, cnt = 0, top = 0;
    18 int c[maxn << 1];
    19 int ans[maxn];
    20 
    21 inline int read() {
    22     int x = 0, y = 1;
    23     char ch = getchar();
    24     while(!isdigit(ch)) {
    25         if(ch == '-') y = -1;
    26         ch = getchar();
    27     }
    28     while(isdigit(ch)) {
    29         x = (x << 1) + (x << 3) + ch - '0';
    30         ch = getchar();
    31     }
    32     return x * y;
    33 }
    34 
    35 inline bool cmp(Query x, Query y) {//按第一维排序 
    36     if(x.s == y.s && x.c == y.c) return x.m < y.m;
    37     else if(x.s == y.s) return x.c < y.c;
    38     return x.s < y.s;
    39 }
    40 
    41 inline int ask(int x) {
    42     int res = 0;
    43     for(; x; x -= (x & -x)) res += c[x];
    44     return res;
    45 }
    46 
    47 inline void add(int x, int y) {
    48     for(; x <= k; x += (x & -x)) c[x] += y;
    49 }
    50 
    51 void solve(int l, int r) {
    52     if(l == r) return;
    53     int mid = l + r >> 1;
    54     solve(l, mid), solve(mid + 1, r);
    55     sort(q + l, q + mid + 1);//排序,让我sb的卡了会,因为不知道sort的排序是左闭右开 
    56     sort(q + mid + 1, q + r + 1);
    57     int x = l;
    58     for(int i = mid + 1; i <= r; ++i) {//用左边区间的答案导出右边区间的答案 
    59         while(x <= mid && q[x].c <= q[i].c) add(q[x].m, q[x].num), x++;//确定了前两维的顺序时,将q[x].m赋上该品种的花的数量,方便右边区间查询 
    60         q[i].sum += ask(q[i].m);//查询 
    61     } 
    62     for(int i = l; i < x; ++i) add(q[i].m, -q[i].num);//还原树状数组 
    63 }
    64 
    65 int main() {
    66     n = read(), k = read();
    67     for(int i = 1; i <= n; ++i)
    68         a[i].s = read(), a[i].c = read(), a[i].m = read();
    69     sort(a + 1, a + n + 1, cmp);
    70     for(int i = 1; i <= n; ++i) {
    71         cnt++;
    72         if(a[i] != a[i + 1]) {
    73             q[++top] = a[i];
    74             q[top].num = cnt;//对于某一品种花有多少个 
    75             cnt = 0;
    76         }
    77     }
    78     solve(1, top);
    79     for(int i = 1; i <= top; ++i) ans[q[i].sum + q[i].num - 1] += q[i].num;
    80     //一朵花的评级=该朵花的美丽值超越的花的数量+属性相同的花的总量(包含自己)-1
    81     //因为题目:定义一朵花A比另一朵花B要美丽,当且仅Sa>=Sb,Ca>=Cb,Ma>=Mb。 
    82     for(int i = 0; i < n; ++i) printf("%d
    ", ans[i]); 
    83     //评级可能有0的 
    84     return 0;
    85 }
  • 相关阅读:
    emWin(ucGui) MULTIEDIT控件的按键响应处理 worldsing
    emWin(ucGui) Edit控件数值模式 ——符号编辑 worldsing
    利用NotePad++ 格式化代码(格式标准化) worldsing
    emWin(ucGui)的Edit控件退格处理方法 worldsing
    Keil MDK Code、RO-data、RW-data、ZI-data数据段
    emWin(ucGUI)在PC机上模拟的按键响应多次解决办法 worldsing
    emWin5.24 VS2008模拟LCD12864 stm32 RTX移植 【worldsing笔记】
    VS2008 工程中部分文件不参与编译 从生成中排除【Worldsing笔记】
    3.emWin5.26(ucGui)VS2008 2-D图形库-基本绘图【Worldsing笔记】
    AVR M8 暴力加压 口味有点重慎入 【worldsing】
  • 原文地址:https://www.cnblogs.com/ywjblog/p/10397969.html
Copyright © 2020-2023  润新知