HDU 5126 stars 4维偏序, CDQ套CDQ

题目传送门

题意:在一个星空中,按着时间会出现一些点,现在john想知道,在某个时间内有多少个星星是的坐标是满足条件的。(x1<=x<=x2, y1 <= y <= y2, z1 <= z <= z2).
题解:先简化问题,如果我们就统计出现所有 x <= x2 , y <= y2, z <= z2的点的话,这就是一个4维偏序题。

对于这个统计点数来说, 我们先按照题目给定点的顺序来进行CDQ, 这样在CDQ内只有左边的添加点会对右边的询问点产生影响,然后我们再把这些会对答案找出影响的点拿出来,

对这些点进行关于X轴内一个sort,对于sort完的结果,我们再进行cdq, 这样在cdq内还是只有左边的左边的添加点会对右边的询问点产生影响,然后我们再把这些会对答案找出影响的点拿出来。

这样就变成了2维偏序题了, 再对y sort, 然后for一遍询问答案把答案加进去就好了。

现在的问题就变成了怎么询问这个长方体内点的个数。 我们可以用差分的思想去维护这个矩形。

我们对一次询问可以拆成8次询问。

Q1( X1-1, Y1-1, Z2) Q2 (X1-1, Y2, Z2) Q3 (X2, Y1-1, Z2) Q4(X2,Y2,Z2)

Q5( X1-1, Y1-1, Z1-1) Q6 (X1-1, Y2, Z1-1) Q7 (X2, Y1-1, Z1-1) Q8(X2,Y2,Z1-1)

可以发现 Q1-Q2-Q3+Q4 得到的是  z <= z2    x1<=x <= x2 && y1 <= y <= y2 的点的个数和。

现在我们在减去 z <= z1-1 x1<=x <= x2 && y1 <= y <= y2 的个数和就是答案了。

在CDQ的过程中, 我们可以加上一个剪枝 即对于这个CDQ来说,如果左边没有添加点 或者 右边没有询问点 就再进行处理了, 因为不会对答案造成影响。

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
  4 #define LL long long
  5 #define ULL unsigned LL
  6 #define fi first
  7 #define se second
  8 #define pb push_back
  9 #define lson l,m,rt<<1
 10 #define rson m+1,r,rt<<1|1
 11 #define lch(x) tr[x].son[0]
 12 #define rch(x) tr[x].son[1]
 13 #define max3(a,b,c) max(a,max(b,c))
 14 #define min3(a,b,c) min(a,min(b,c))
 15 typedef pair<int,int> pll;
 16 const int inf = 0x3f3f3f3f;
 17 const LL INF = 0x3f3f3f3f3f3f3f3f;
 18 const LL mod =  (int)1e9+7;
 19 const int N = 1e6 + 100;
 20 struct Node{
 21     int x, y, z, op, id;
 22 }A[N], B[N], C[N];
 23 int ans[N];
 24 int zz[N];
 25 int tot = 0;
 26 int zsz;
 27 int bit[N];
 28 void add(int x, int v){
 29     while(x <= zsz){
 30         bit[x] += v;
 31         x += x & (-x);
 32     }
 33 }
 34 int query(int x){
 35     int ret = 0;
 36     while(x > 0){
 37         ret += bit[x];
 38         x -= x & (-x);
 39     }
 40     return ret;
 41 }
 42 bool cmp_x(Node & n1, Node & n2){
 43     if(n1.x != n2.x) return n1.x < n2.x;
 44     if(n1.y != n2.y) return n1.y < n2.y;
 45     if(n1.z != n2.z) return n1.z < n2.z;
 46     return n1.id < n2.id;
 47 }
 48 bool cmp_y(Node & n1, Node & n2){
 49     if(n1.y != n2.y) return n1.y < n2.y;
 50     if(n1.z != n2.z) return n1.z < n2.z;
 51     return n1.id < n2.id;
 52 }
 53 void cdq(int l, int r){
 54     if(l >= r) return ;
 55     int m = l+r >> 1;
 56     cdq(l, m); cdq(m+1, r);
 57     int k = 0;
 58     for(int i = l; i <= m; i++)
 59         if(!B[i].id) C[++k] = B[i];
 60     for(int i = m+1; i <= r; i++)
 61         if(B[i].id)  C[++k] = B[i];
 62     if(C[1].id != 0 || C[k].id == 0) return ;/// 剪枝
 63     sort(C+1, C+1+k, cmp_y);
 64     for(int i = 1; i <= k; i++){
 65         if(C[i].op)
 66             ans[C[i].id] += query(C[i].z) * C[i].op;
 67         else
 68             add(C[i].z, 1);
 69     }
 70     for(int i = 1; i <= k; i++){
 71         if(C[i].op);
 72         else add(C[i].z, -1);
 73     }
 74 }
 75 void CDQ(int l, int r){
 76     if(l == r) return ;
 77     int m = l+r >> 1;
 78     CDQ(l,m); CDQ(m+1,r);
 79     int k = 0;
 80     for(int i = l; i <= m; i++)
 81         if(!A[i].id)  B[++k] = A[i];
 82     for(int i = m+1; i <= r; i++)
 83         if(A[i].id)   B[++k] = A[i];
 84     if(B[1].id != 0 || B[k].id == 0) return ;/// 剪枝
 85     sort(B+1, B+1+k, cmp_x);
 86     cdq(1,k);
 87 }
 88 
 89 inline void nownode(int x, int y, int z, int op, int id){
 90     ++tot; A[tot].x = x; A[tot].y = y; zz[tot] = z;
 91     A[tot].z = z; A[tot].op = op; A[tot].id = id;
 92 }
 93 int main(){
 94     int T;
 95     scanf("%d", &T);
 96     while(T--){
 97         int n, op, x1, y1, z1, x2, y2, z2, m = 0;
 98         tot = 0;
 99         scanf("%d", &n);
100         for(int i = 1; i <= n; i++){
101             scanf("%d", &op);
102             if(op == 1){
103                 scanf("%d%d%d", &x1, &y1, &z1);
104                 nownode(x1, y1, z1, 0, 0);
105             }
106             else {
107                 m++;
108                 ans[m] = 0;
109                 scanf("%d%d%d", &x1, &y1, &z1);
110                 scanf("%d%d%d", &x2, &y2, &z2);
111                 nownode(x2,y2,z2,1,m);
112                 nownode(x1-1,y1-1,z2,1,m);
113                 nownode(x2,y1-1,z2,-1,m);
114                 nownode(x1-1,y2,z2,-1,m);
115 
116                 nownode(x2,y2,z1-1,-1,m);
117                 nownode(x1-1,y1-1,z1-1,-1,m);
118                 nownode(x2,y1-1,z1-1,1,m);
119                 nownode(x1-1,y2,z1-1,1,m);
120             }
121         }
122         sort(zz+1, zz+tot+1);
123         zsz = unique(zz+1, zz+tot+1) - zz - 1;
124         for(int i = 1; i <= tot; i++)
125             A[i].z = lower_bound(zz+1, zz+1+zsz, A[i].z) - zz;
126         CDQ(1, tot);
127         for(int i = 1; i <= m; i++)
128             printf("%d
", ans[i]);
129     }
130     return 0;
131 }
View Code
原文地址:https://www.cnblogs.com/MingSD/p/9869522.html