• cdq分治(偏序)


    偏序问题:

    https://www.luogu.org/blog/Owencodeisking/post-xue-xi-bi-ji-cdq-fen-zhi-hu-zheng-ti-er-fen

    优质题目:

    https://oi.men.ci/tag/cdq/

    看思想:

    https://www.cnblogs.com/MyNameIsPc/p/9297296.html

    https://www.cnblogs.com/mlystdcall/p/6219421.html

    三维偏序

    维度a,b,c

    [m+1,r]对于[l,m]满足条件的个数

    经过排序过,

    a:

    [m+1,r]的任意一个数比[l,m]的任意一个数大

    这一维解决了

    b:

    区间合并时是按照b从小到大添加的

    这一维解决了

    c:

    树状数组记录

    注意:

    1.去掉相同的项

    如果不那么做,如果[m+1,r]中的一项与[l,m]中的一项相同,就会出错。

    2.[l,m]的数值添加到树状数组中,最后要去掉。

    https://loj.ac/problem/112

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <set>
      8 #include <map>
      9 #include <queue>
     10 #include <iostream>
     11 using namespace std;
     12 
     13 #define ll long long
     14 
     15 const int maxn=1e5+10;
     16 const int inf=1e9;
     17 const double eps=1e-8;
     18 const int maxf=2e5+10;
     19 
     20 int maxv,f[maxf],sum[maxn];
     21 
     22 struct node
     23 {
     24     int a,b,c,g,v;///排b,c这两个维度只是为了找到相同的(a,b,c),没有其它的意义
     25     bool operator<(const node &y) const
     26     {
     27         if (a==y.a)
     28         {
     29             if (b==y.b)
     30                 return c<y.c;
     31             return b<y.b;
     32         }
     33         return a<y.a;
     34     }
     35 }d[maxn],e[maxn];
     36 
     37 void update(int x,int y)
     38 {
     39     while (x<=maxv)
     40     {
     41         f[x]+=y;
     42         x+=x&-x;
     43     }
     44 }
     45 
     46 int cal(int x)
     47 {
     48     int sum=0;
     49     while (x)
     50     {
     51         sum+=f[x];
     52         x-=x&-x;
     53     }
     54     return sum;
     55 }
     56 
     57 void cdq(int l,int r)
     58 {
     59     int m=(l+r)>>1;
     60     if (l==r)
     61         return;
     62     cdq(l,m),cdq(m+1,r);
     63     int i,j,k;
     64     for (i=l;i<=r;i++)
     65         d[i]=e[i];
     66     i=l,j=m+1,k=l;
     67     while (i<=m && j<=r)
     68     {
     69         if (d[i].b<=d[j].b)
     70             update(d[i].c,d[i].g),e[k++]=d[i++];
     71         else
     72             d[j].v+=cal(d[j].c),e[k++]=d[j++];
     73     }
     74     while (i<=m)
     75         update(d[i].c,d[i].g),e[k++]=d[i++];
     76     while (j<=r)
     77         d[j].v+=cal(d[j].c),e[k++]=d[j++];
     78     for (i=l;i<=m;i++)
     79         update(d[i].c,-d[i].g);
     80 }
     81 
     82 int main()
     83 {
     84     int n,m,i;
     85     scanf("%d%d",&n,&maxv);
     86     for (i=1;i<=n;i++)
     87         scanf("%d%d%d",&d[i].a,&d[i].b,&d[i].c),d[i].g=1;
     88     sort(d+1,d+n+1);
     89     e[1]=d[1],m=1;
     90     for (i=2;i<=n;i++)
     91         if (d[i].a==d[i-1].a && d[i].b==d[i-1].b && d[i].c==d[i-1].c)
     92             e[m].g++;
     93         else
     94             e[++m]=d[i];
     95     cdq(1,m);
     96     for (i=1;i<=m;i++)
     97         sum[d[i].v+d[i].g-1]+=d[i].g;
     98     for (i=0;i<n;i++)
     99         printf("%d
    ",sum[i]);
    100     return 0;
    101 }
    102 /*
    103 3 100
    104 1 1 1
    105 2 2 2
    106 3 3 3
    107 */

    later

    https://oi.men.ci/bzoj-2253/

    「BZOJ 2253」纸箱堆叠 - CDQ 分治 + DP

  • 相关阅读:
    洛谷 P2831 [NOIP2016]愤怒的小鸟
    洛谷 P1736 创意吃鱼法
    洛谷 P2347 砝码称重 + bitset简析
    洛谷 P3384 [模板] 树链剖分
    洛谷 P1038 [NOIP2012] 借教室
    洛谷 P3959 [NOIP2017]宝藏 题解
    洛谷 AT2167 Blackout 题解
    洛谷 P1246 编码 题解
    C#中ref关键字的用法总结
    C#中的值传递与引用传递(in、out、ref)
  • 原文地址:https://www.cnblogs.com/cmyg/p/10698408.html
Copyright © 2020-2023  润新知