zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    day 17
    day 16
    信息系统项目管理师 教程学习 第一章
    服务器安全防护
    少有人走的路
    Python文件学习
    测试新文章
    测试
    python基础 一、 数值类型、序列类型和散列类型
    apache No input filespecified
  • 原文地址:https://www.cnblogs.com/MingSD/p/9869522.html
Copyright © 2011-2022 走看看