HDU5126 stars(CDQ分治)

传送门

大意:

向三维空间中加点,询问一个三维区间中点的个数。

解题思路:

带修改CDQ,将修改和询问一起插入CDQ分治询问。

(询问可以由8个前缀和加减操作实现)

其中第一层CDQ维护x有序。

第二层CDQ维护y有序并且将z离线处理完更新答案。

注意要将原数组的辅助数组推入第二层CDQ否则会将顺序毁坏。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 const int N=1000001;
  5 const int M=4000001;
  6 struct data{
  7     int t;
  8     int x;
  9     int y;
 10     int tz;
 11     int z;
 12     int c;
 13     bool left;
 14 }d[N],o[N],tmp[N],stdata;
 15 int n,T;
 16 int cnt;
 17 int tot;
 18 int ans[N];
 19 int sek[N];
 20 int line[M];
 21 bool cmpz(data a,data b){return a.tz<b.tz;}
 22 bool cmpb(data a,data b){return a.t<b.t;}
 23 int lowbit(int x){return x&(-x);}
 24 void update(int pos,int v)
 25 {
 26     while(pos<=tot)
 27     {
 28         line[pos]+=v;
 29         pos+=lowbit(pos);
 30     }
 31     return ;
 32 }
 33 int query(int pos)
 34 {
 35     int ans=0;
 36     while(pos)
 37     {
 38         ans+=line[pos];
 39         pos-=lowbit(pos);
 40     }
 41     return ans;
 42 }
 43 void Get(void)
 44 {
 45     tot=1;
 46     std::sort(d+1,d+cnt+1,cmpz);
 47     d[1].z=1;
 48     for(int i=2;i<=cnt;i++)
 49     {
 50         if(d[i].tz!=d[i-1].tz)
 51             tot++;
 52         d[i].z=tot;
 53     }
 54     std::sort(d+1,d+cnt+1,cmpb);
 55     return ;
 56 }
 57 void cdq(int l,int r)
 58 {
 59     if(l==r)
 60         return ;
 61     int mid=(l+r)>>1;
 62     cdq(l,mid);
 63     cdq(mid+1,r);
 64     int j=l;
 65     for(int i=mid+1;i<=r;i++)
 66     {
 67         for(;j<=mid&&o[j].y<=o[i].y;j++)
 68             if(!o[j].c&&o[j].left)
 69                 update(o[j].z,1);
 70         if(o[i].left)
 71             continue;
 72         ans[o[i].t]+=o[i].c*query(o[i].z);
 73     }
 74     for(int i=l;i<j;i++)
 75         if(!o[i].c&&o[i].left)
 76             update(o[i].z,-1);
 77     int sta1=l,sta2=mid+1;
 78     for(int i=l;i<=r;i++)
 79         if(sta1<=mid&&(sta2>r||o[sta1].y<=o[sta2].y))
 80             tmp[i]=o[sta1++];
 81         else
 82             tmp[i]=o[sta2++];
 83     for(int i=l;i<=r;i++)
 84         o[i]=tmp[i];
 85     return ;
 86 }
 87 void CDQ(int l,int r)
 88 {
 89     if(l==r)
 90         return ;
 91     int mid=(l+r)>>1;
 92     CDQ(l,mid);
 93     CDQ(mid+1,r);
 94     for(int i=l;i<=r;i++)
 95         d[i].left=(i<=mid);
 96     int sta1=l,sta2=mid+1;
 97     for(int i=l;i<=r;i++)
 98         if(sta1<=mid&&(sta2>r||d[sta1].x<=d[sta2].x))
 99             o[i]=d[sta1++];
100         else
101             o[i]=d[sta2++];
102     for(int i=l;i<=r;i++)
103         d[i]=o[i];
104     cdq(l,r);
105     for(int i=l;i<=r;i++)
106         d[i].left=false;
107     return ;
108 }
109 int main()
110 {
111     //freopen("a.in","r",stdin);
112     scanf("%d",&T);
113     while(T--)
114     {
115         for(int i=1;i<=n;i++)
116             ans[i]=0;
117         for(int i=1;i<=cnt;i++)
118             d[i]=tmp[i]=stdata;
119         cnt=n=0;
120         scanf("%d",&n);
121         for(int i=1;i<=n;i++)
122         {
123             int cmd;
124             scanf("%d",&cmd);
125             sek[i]=cmd;
126             if(cmd==1)
127             {
128                 int x,y,z;
129                 scanf("%d%d%d",&x,&y,&z);
130                 d[++cnt]=(data){i,x,y,z,0,0,0};
131             }else{
132                 int ax,ay,az,bx,by,bz;
133                 scanf("%d%d%d%d%d%d",&ax,&ay,&az,&bx,&by,&bz);
134                 if(ax>bx)
135                     std::swap(ax,bx);
136                 if(ay>by)
137                     std::swap(ay,by);
138                 if(az>bz)
139                     std::swap(az,bz);
140                 ax--,ay--,az--;
141                 d[++cnt]=(data){i,ax,ay,az,0,-1,0};
142                 d[++cnt]=(data){i,ax,ay,bz,0,1,0};
143                 d[++cnt]=(data){i,ax,by,az,0,1,0};
144                 d[++cnt]=(data){i,bx,ay,az,0,1,0};
145                 d[++cnt]=(data){i,ax,by,bz,0,-1,0};
146                 d[++cnt]=(data){i,bx,ay,bz,0,-1,0};
147                 d[++cnt]=(data){i,bx,by,az,0,-1,0};
148                 d[++cnt]=(data){i,bx,by,bz,0,1,0};
149             }
150         }
151         
152         Get();
153         CDQ(1,cnt);
154         for(int i=1;i<=n;i++)
155             if(sek[i]==2)
156                 printf("%d\n",ans[i]);
157     }
158     return 0;
159 }

 

posted @ 2018-12-13 19:02  Unstoppable728  阅读(237)  评论(0编辑  收藏  举报