HDU5126---stars (CDQ套CDQ套 树状数组)

题意:Q次操作,三维空间内 每个星星对应一个坐标,查询以(x1,y1,z1) (x2,y2,z2)为左下顶点 、右上顶点的立方体内的星星的个数。

注意Q的范围为50000,显然离散化之后用三维BIT会MLE。 我们可以用一次CDQ把三维变成二维,变成二维之后就有很多做法了,树套树,不会树套树的话还可以继续CDQ由二维变成一维,,变成一维了就好做了,,最基本的数据结构题目了。。

不得不说、CDQ真的很神奇。

下面做法就是CDQ套CDQ套树状数组。

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 const int maxn = 50010;
  7 inline int lowbit (int x)
  8 {
  9     return x & -x;
 10 }
 11 int c[maxn*9],MAX;
 12 void add(int x,int d)
 13 {
 14     while (x <= MAX)
 15     {
 16         c[x] += d;
 17         x += lowbit(x);
 18     }
 19 }
 20 int sum(int x)
 21 {
 22     int ans = 0;
 23     while (x)
 24     {
 25         ans += c[x];
 26         x -= lowbit (x);
 27     }
 28     return ans;
 29 }
 30 struct Point
 31 {
 32     int x,y,z;
 33     int kind,idx,delt;
 34     Point() {}
 35     Point(int _x,int _y,int _z,int _delt,int _kind,int _idx):
 36         x(_x), y(_y), z(_z), delt(_delt), kind(_kind), idx(_idx) {}
 37
 38 } star[maxn << 4],star3[maxn << 4];
 39 int ans[maxn<<1];
 40 bool cmp1(const Point &p1,const Point &p2)
 41 {
 42     return p1.x < p2.x || ((p1.x == p2.x) && (p1.idx < p2.idx) );
 43 }
 44 bool cmp2(const Point &p1,const Point &p2)
 45 {
 46     return p1.y < p2.y || ((p1.y == p2.y) && (p1.idx < p2.idx) );
 47 }
 48 void CDQ2(int l,int r)
 49 {
 50     if (l >= r)
 51         return;
 52     int mid = (l + r) >> 1;
 53     CDQ2(l,mid);
 54     CDQ2(mid+1,r);
 55     int j = l;
 56     for (int i = mid + 1; i <= r; i++)
 57     {
 58         if (star3[i].kind == 1)
 59         {
 60             for ( ; j <= mid  && (star3[j].y <= star3[i].y); j++)
 61             {
 62                 if (star3[j].kind == 0)
 63                     add(star3[j].z,star3[j].delt);
 64             }
 65             ans[star3[i].idx] += sum(star3[i].z) * star3[i].delt;
 66         }
 67     }
 68     for (int i = l; i < j; i++)
 69     {
 70         if (star3[i].kind == 0)
 71             add(star3[i].z,-star3[i].delt);
 72     }
 73     inplace_merge(star3+l,star3+mid+1,star3+r+1,cmp2);
 74 }
 75 void CDQ1(int l,int r)
 76 {
 77     if (l == r)
 78         return;
 79     int mid = (l + r) >> 1;
 80     CDQ1(l, mid);
 81     CDQ1(mid+1, r);
 82     int tot = 1;
 83     for (int j = l; j <= mid ; j++)
 84         if (star[j].kind == 0)
 85             star3[tot++] = star[j];
 86     for (int i = mid + 1; i <= r; i++)
 87     {
 88         if (star[i].kind == 1)
 89             star3[tot++] = star[i];
 90     }
 91     sort(star3+1,star3+tot,cmp1);
 92     CDQ2(1,tot-1);
 93 }
 94 int vec[maxn << 4],idx;
 95 void hash_(int tot)
 96 {
 97     sort(vec,vec+idx);
 98     idx = unique(vec,vec+idx) - vec;
 99     MAX = idx + 1;
100     for (int i = 1; i <= tot; i++)
101         star[i].z = lower_bound(vec,vec+idx,star[i].z) - vec + 1;
102 }
103 int main(void)
104 {
105 #ifndef ONLINE_JUDGE
106     freopen("in.txt","r",stdin);
107 #endif // ONLINE_JUDGE
108     int T,Q;
109     scanf ("%d",&T);
110     while (T--)
111     {
112         scanf ("%d",&Q);
113         int tot = 1;
114         int totq = 0;
115         idx = 0;
116         memset(c,0,sizeof (c));
117         memset(ans,0,sizeof(ans));
118         for (int i = 1; i <= Q; i++)
119         {
120             int op,x1,y1,z1,x2,y2,z2;
121             scanf ("%d",&op);
122             if (op == 1)
123             {
124                 scanf ("%d%d%d",&x1,&y1,&z1);
125                 star[tot] = Point(x1,y1,z1,1,0,totq);
126                 vec[idx++] = z1;
127                 ans[totq] = -1;
128                 tot++;
129                 totq++;
130             }
131             if (op == 2)
132             {
133                 scanf ("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2);
134                 star[tot] = Point(x1-1, y1-1, z1-1, -1, 1, totq),  vec[idx++] = z1-1, tot++;
135                 star[tot] = Point(x2,   y1-1, z1-1,  1, 1, totq),  vec[idx++] = z1-1, tot++;
136                 star[tot] = Point(x2 ,  y2  , z1-1, -1, 1, totq),  vec[idx++] = z1-1, tot++;
137                 star[tot] = Point(x1-1, y2,   z1-1,  1, 1, totq),  vec[idx++] = z1-1, tot++;
138                 star[tot] = Point(x1-1, y2,   z2  , -1, 1, totq),  vec[idx++] = z2  , tot++;
139                 star[tot] = Point(x2  , y2,   z2  ,  1, 1, totq),  vec[idx++] = z2  , tot++;
140                 star[tot] = Point(x2  , y1-1, z2  , -1, 1, totq),  vec[idx++] = z2  , tot++;
141                 star[tot] = Point(x1-1, y1-1, z2  ,  1, 1, totq),  vec[idx++] = z2  , tot++;
142                 totq++;
143             }
144         }
145         hash_(tot);
146         CDQ1(1,tot-1);
147         for (int i = 0; i < totq; i++)
148             if (~ans[i])
149                 printf("%d\n",ans[i]);
150     }
151     return 0;
152 }
时间: 2024-08-24 02:03:05

HDU5126---stars (CDQ套CDQ套 树状数组)的相关文章

BZOJ3262/洛谷P3810 陌上花开 CDQ分治 三维偏序 树状数组

原文链接http://www.cnblogs.com/zhouzhendong/p/8672131.html 题目传送门 - BZOJ3262 题目传送门 - 落谷P3810 题意 有$n$个元素,第$i$个元素有$a_i$.$b_i$.$c_i$三个属性,设$f(i)$表示满足$a_j\leq a_i$且$b_j\leq b_i$且$c_j\leq c_i$的$j$的数量.对于$d\in [0,n)$,求$f(i)=d$的数量. $n\leq 100000,max\{a_i,b_i,c_i|i

BZOJ 2244 SDOI2011 拦截导弹 CDQ分治/二维树状数组

题目大意:给定一个序列,每个元素是一个二元组,等概率选择一LIS,求LIS长度以及每个元素被选中的概率 第一问CDQ分治裸上 第二问用每个元素所在的LIS个数/总LIS个数就是答案 每个元素所在的LIS自己必选,然后统计前面的方案数和后面的方案数 以前面的方案数为例,令f[x]为以x结尾的LIS长度,那么有DP方程: g[i]=Σg[j] (f[j]+1=f[i],j<i,a[j].x<a[i].x,a[j].y<a[i].y) 将所有元素按f值排序,分层DP,每层DP是一个三维偏序,上

【树状数组】【权值分块】bzoj2352 Stars

经典问题:二维偏序.给定平面中的n个点,求每个点左下方的点的个数. 因为 所有点已经以y为第一关键字,x为第二关键字排好序,所以我们按读入顺序处理,仅仅需要计算x坐标小于<=某个点的点有多少个就行. 这就是所说的:n维偏序,一维排序,二维树状数组,三维 分治 Or 树状数组套平衡树…… <法一>树状数组. 1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 using name

[CDQ分治][树状数组][树套树] Jzoj P3197 K大数查询

Description 有n 个位置和m 个操作.操作有两种,每次操作如果是1 a b c 的形式,表示往第a 个位置到第b 个位置每个位置加入一个数c.如果操作形如2 a b c 的形式,表示询问从第a 个位置到第b 个位置,第c 大的数是多少. Input 在输入文件sequence.in 中,第一行两个数n,m.意义如题目描述.接下来m 行每行形如1 a b c 或者2 a b c 如题目描述. Output 在输出文件sequence.out 中,对于每个询问回答k 大数是多少. Sam

HDU 5126 stars cdq分治+树状数组

题目链接:点击打开链接 题意: T个case n个操作 1. (x,y,z) 在三维平面的点上增加1 2.询问区间范围内的权值和. 思路: cdq分治套cdq分治,然后套树状数组即可.. #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #include <string.h> #inclu

BZOJ3295 动态逆序对 树套树, 树状数组套线段树(主席树)

Orz黄学长,蒟蒻在黄学长的带领下,通过阅读黄学长的代码!终于会了这道题! 首先我想先说一下这道题的思路(准确来说是黄学长的). 很明显,树状数组应该不用讲吧!关键是内存怎么开,维护一些什么样的数据? 其实我们通过观察,很快可以发现,你维护被删的数比维护所有的数轻松多了(不管是空间上,还是时间上).所以我们就可以从这方面想!(其实我一开始的思路,因为这道题我已经看过很久了,一直想写,毕竟是白书里面的一道例题嘛!一开始,蒟蒻的我是打算这样的用树状数组套权值线段树,并且是维护所有的数,我发现空间不够

hdu_5324_Boring Class(cdq分治+树状数组)

题目链接:hdu_5324_Boring Class 题意: 给出n个二维点对,求LIS长度和编号字典序最小的LIS(x非增,y非减) 题解: dp[i]=max(dp[j]) (i>j,l[i]>=l[j],r[i]<=r[i]) 一看就是三维偏序问题. 如果树套树写的好,空间开的大的话,一样可以过,不过这里还是用cdq分治套树状数组好写一点. 用lowbit来维护dp[j]的最大值,然后因为要字典序最小,所以从后往前dp. 1 #include<bits/stdc++.h>

bzoj 1176 [Balkan2007]Mokia - CDQ分治 - 树状数组

Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000. Input 第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小 接下来每行为一下三种输入之一(不包含引号): "1 x y a" "2 x1 y1 x2 y2" "3" 输入1:你需要把(x,y)(第x行第y列)的格子权值增加a 输入

XJOI NOIP2015模拟赛Day1 T2 ctps bitset优化 或 排序+cdq分治+树状数组+平衡树

题意: 4维空间中有1个点集A,|A|=n,用(a,b,c,d)表示每个点. 共有m个询问,每次询问输入一个点(a,b,c,d),求最大的S,其中S={p|p∈A且ap<=a,bp<=b,cp<=c,dp<=d},输出|S| 输入格式: 第一行n 接下来n行有n个4维点对 第n+2行有一个数m 再接下来m行每行有一个四维点对,表示每个询问 输出格式: 对于每个询问输出一个数 **方法:**bitset优化 或 排序+cdq分治+树状数组+平衡树 解析: 神题,考场不会,暴力骗40,