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 }