偏序问题:
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