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\n",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

 

posted @ 2019-04-12 20:35  congmingyige  阅读(328)  评论(0编辑  收藏  举报