• hdu 5126 cdq+Treap+BIT


    这题说的是给了三维空间然后操作 寻求在 x1,y1,z1    x2, y2, z2; (x1<x2, y1<y2,z1<z2) 计算出在 以这两个端点为右下和左上端点的方体内的点的个数。CDQ 分治第一次听说,

    在一个方体内使用容斥原理,然后不断的将剩下的点分成两个部分,然后这样不断地下去,对于每个部分在进行一次CDQ然后,再使用BIT求解,这样我们可以看看他这神奇的CDQ,他先是这样的,第一次CDQ先对在区间内的点进行x轴排序,排完后然后将这些点按照y轴进行合并,这样做的好处是想想二分后的一部分在一侧另一部分只会用到前一部分的,用这种方法可以让后面的所有的点都得到他被包含的查询内、

    cdq套cdq套bit

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <string.h>
    using namespace std;
    const int maxn=50005;
    struct point{
       int x,y,z,delt,qnum,kind;
       point(){}
       point(int a,int b, int c,int d,int e,int f){
         this->x=a;this->y=b;this->z=c;this->delt=d;
         this->qnum=e; this->kind=f;
       }
    }star[maxn*8],start3[maxn*8];
    int Z[maxn*8],tot,qnum,ans[maxn*8],N,C[maxn*8];
    bool use[maxn*8];
    int lowbit(int x){ return x&(-x);   }
    void aDD(int loc, int val){
          while(loc<=N){
            C[loc]+=val;
            loc+=lowbit(loc);
          }
    }
    int sum(int loc){
        int s=0;
        while(loc>0){
            s+=C[loc];
            loc-=lowbit(loc);
        }
        return s;
    }
    void add(int x,int y,int z,int delt,int qnum,int kind ){
         star[tot]=point(x,y,z,delt,qnum,kind);
         Z[tot]=z;++tot;
    }
    void scatter(){
        sort(Z,Z+tot);
        N=unique(Z,Z+tot)-Z;
        for(int i=0; i<tot; ++i)
             star[i].z=lower_bound(Z,Z+N,star[i].z)-Z+1;
    }
    bool cmp1(point A, point B){
      return A.x<B.x||(A.x==B.x&&A.qnum<B.qnum);
    }
    bool cmp2(point A, point B){
       return A.y<B.y||(A.y==B.y&&A.qnum<B.qnum);
    }
    void CDQ2(int L, int R){
        if(L>=R) return ;
        int mid=(R+L)>>1;
        CDQ2(L,mid);
        CDQ2(mid+1,R);
        int j=L;
        for(int i=mid+1;i<=R; ++i){
    
             for( ;j<=mid && ( start3[j].y <= start3[i].y ) ; ++j )
                if(start3[j].kind==0){
                 aDD(start3[j].z,start3[j].delt);
             }
             ans[start3[i].qnum]+=sum(start3[i].z)*start3[i].delt;
        }
        for(int i=L; i<j; ++i)
            if(start3[i].kind==0)
                aDD(start3[i].z,-start3[i].delt);
        inplace_merge(start3+L,start3+mid+1,start3+R+1,cmp2);
    }
    void CDQ1(int L, int R){
        if(L>=R) return ;
        int mid =(L+R)>>1;
        CDQ1(L, mid );
        CDQ1(mid+1,R);
        int num=0;
        for(int i=L; i<=mid; ++i)
            if(star[i].kind==0)
             start3[num++]=star[i];
        for(int i=mid+1;i<=R; ++i)
             if(star[i].kind==1)
              start3[num++]=star[i];
        sort(start3,start3+num,cmp1);
        CDQ2(0,num-1);
    }
    int main()
    {
       int cas;
       scanf("%d",&cas);
       memset(use,false,sizeof(use));
       memset(ans,0,sizeof(ans));
       while(cas--){
           int Q ;
           tot=qnum=0;
           scanf("%d",&Q);
           for(int i=0; i<Q; ++i){
               int A;
               scanf("%d",&A);
               if(A==1){
                    int x,y,z;
                    scanf("%d%d%d",&x,&y,&z);
                   add( x, y, z, 1, qnum, 0);qnum++;
               }else{
                    int x1,y1,z1,x2,y2,z2;
                    use[qnum]=true;
                    scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
                    add(x1-1,y1-1,z1-1,-1,qnum,1);
                    add(x1-1,y1-1,z2  , 1,qnum,1);
                    add(x1-1,y2  ,z1-1, 1,qnum,1);
                    add(x1-1,y2  ,z2  ,-1,qnum,1);
                    add(x2  ,y2  ,z1-1,-1,qnum,1);
                    add(x2  ,y2  ,z2  , 1,qnum,1);
                    add(x2  ,y1-1,z1-1, 1,qnum,1);
                    add(x2  ,y1-1,  z2,-1,qnum,1);
                    qnum++;
                }
    
           }
           scatter();
           CDQ1(0,tot-1);
           for(int i=0; i<qnum; ++i){
    
            if(use[i]==true) printf("%d
    ",ans[i]);
               use[i]=false; ans[i]=0;
            }
       }
    
        return 0;
    }
    View Code

    这里有一个方法使用cdq里面套了一个BIT 然后套 了一个Treap 使用cdq分治,然后离散了x 然后在BiT上放上棵Treap,通过Treap 去找到对应的个数

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <string.h>
    #include <cstdlib>
    using namespace std;
    const int maxn=50000+10;
    struct Node{
       Node *ch[2];
       int r;
       int y;
       int spoint;
       int loc;
       void maintain(){
             spoint=loc;
             if(ch[0]!=NULL) spoint+=ch[0]->spoint;
             if(ch[1]!=NULL) spoint+=ch[1]->spoint;
       }
       Node(int v):y(v){ r=rand(); spoint=1; loc=1; ch[0]=ch[1]=NULL; }
       int cmp(int x){
           if(x==y) return -1;
           return x<y?0:1;
       }
    };
    Node *T[maxn*3];
    int now[maxn*3],Time;
    void removetree(Node *&o){
        if(o->ch[0]!=NULL) removetree(o->ch[0]);
        if(o->ch[1]!=NULL) removetree(o->ch[1]);
        delete o;
        o=NULL;
    }
    void rotate(Node *&o, int d){
      Node *k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o;
      o->maintain(); k->maintain(); o=k;
    }
    void insert(Node *&o, int y){
        if(o==NULL){
           o=new Node(y);
        }else{
           int d=o->cmp(y);
           if(d==-1){
              o->loc++;
           }else{
              insert(o->ch[d],y);
              if( o->ch[d]->r > o->r ) rotate(o,d^1);
           }
        }
        o->maintain();
    }
    struct point{
         int x1,x2,y1,y2,z;
         int op,q;
         point(int x1=0,int y1=0,int x2=0, int y2=0,int z=0, int op=0, int q=0){
             this->x1=x1;this->y1=y1; this->x2=x2;this->y2=y2; this->z=z;
             this->op=op; this->q=q;
    
         }
    }P[maxn*3],s1[maxn*3];
    int cntx[maxn*3],ans[maxn],point_cnt,x_cnt;
    bool vis[maxn];
    bool cmp(point A, point B){
        if(A.z!=B.z)return A.z<B.z;
        return A.q<B.q;
    }
    int lowbit(int x){
      return x&(-x);
    }
    void add(int loc, int y){
          while(loc<=x_cnt){
             if( now[ loc ] != Time ){
                    if(T[loc]!=NULL)removetree(T[loc]);
                    T[loc]=NULL;
                    now[loc]=Time;
             }
             insert(T[loc],y);
             loc+=lowbit(loc);
          }
    }
    int search(Node *&o , int y){
       if(o==NULL) return 0;
       if(y<o->y) return search(o->ch[0],y);
       else {
         int a=search(o->ch[1],y);
         if(o->ch[0]!=NULL)
            a+=o->ch[0]->spoint;
         a+=o->loc;
         return a;
       }
    }
    int sum(int loc, int y){
        int ans=0;
        while(loc>0){
            if(now[loc]==Time) ans+=search(T[loc],y);
            loc-=lowbit(loc);
        }
        return ans;
    }
    void cdq_fz(int L, int R){
          if(L>=R) return ;
          int mid=(L+R)/2;
          int e=0;
          cdq_fz(     L, mid );
          cdq_fz( mid+1,   R );
          for(int i=L; i<=mid; ++i)
            if(P[i].q==0) s1[e++]=P[i];
          for(int i=mid+1; i<=R; ++i)
            if(P[i].q!=0) s1[e++]=P[i];
           sort(s1,s1+e,cmp);
           Time++;
           for(int i=0; i<e; ++i)
            if(s1[i].q==0){
                 add(s1[i].x2,s1[i].y2);
            }else{
                 ans[s1[i].q]+=s1[i].op*sum(s1[i].x2,   s1[i].y2);
                 ans[s1[i].q]-=s1[i].op*sum(s1[i].x1,   s1[i].y2);
                 ans[s1[i].q]-=s1[i].op*sum(s1[i].x2,   s1[i].y1);
                 ans[s1[i].q]+=s1[i].op*sum(s1[i].x1,   s1[i].y1);
            }
    }
    void solve(){
        int N;
         scanf("%d",&N);
         for(int cc=1; cc<=N; ++cc){
             int op,x1,x2,y1,y2,z1,z2;
             scanf("%d",&op);
             if(op==1){
                 scanf("%d%d%d",&x1,&y1,&z1);
                 P[point_cnt++]=point(x1,y1,x1,y1,z1,1,0);
                 cntx[x_cnt++]=x1;
                 vis[cc]=false;
             }else{
                 scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
                 cntx[x_cnt++]=x1-1;
                 cntx[x_cnt++]=x2;
                 P[point_cnt++]=point(x1-1,y1-1,x2,y2,  z2, 1,cc);
                 P[point_cnt++]=point(x1-1,y1-1,x2,y2,z1-1,-1,cc);
                 vis[cc]=true;
             }
         }
         sort(cntx,cntx+x_cnt);
         x_cnt=unique(cntx,cntx+x_cnt)-cntx;
         for(int i=0 ; i<point_cnt ; ++i ){
            if(P[i].q!=0)
            P[i].x1=lower_bound(cntx,cntx+x_cnt,  P[i].x1)-cntx+1;
            P[i].x2=lower_bound(cntx,cntx+x_cnt,  P[i].x2)-cntx+1;
        }
         cdq_fz(0,point_cnt-1);
         for( int i=1; i<=N; ++i )
             if( vis[i] ) printf("%d
    ",ans[i]);
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--){
             memset(ans,0,sizeof(ans));
             memset(now,0,sizeof(now));
             x_cnt = point_cnt=0;
             Time=1;
             solve();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    SPI传输协议笔记
    Linux power supply class
    linux ramdisk 参数问题
    Android事件处理过程分析
    PWM 参数计算
    6.828 lab3
    6.828 lab1
    i.MX53 上电启动过程
    linux jiffies的比较
    在arm板上安装Debian
  • 原文地址:https://www.cnblogs.com/Opaser/p/4183590.html
Copyright © 2020-2023  润新知