题目
这是个复杂的世界。人类社会,自然界,还有地球之外的银河……
每一天日出日落,人来人往,步履匆匆。究竟是为什么呢?那支配着一切的至高无上的法则又是否存在呢?Theresa知道,这个问题并不是一朝一夕就可以解答的,只有在仔细、深入的观察和思考以后,才有可能将所有支离破碎的线索联系起来,从而隐约窥见真实的答案。
于是,Theresa经常思考生活中遇到的大大小小的问题。为什么港台出版的书籍里印刷的汉字她一个也不认识呢?为什么隔夜的白开水中富含一氧化二氢呢?为什么每年都有一段时间Gmail邮箱上不去呢?
为了更加系统、科学地分析这些问题,Theresa决定向你求助。
长话短说,Theresa想请你帮助她实现一个数据结构。这个数据结构的功能是在空间直角坐标系中维护一个点的集合,并支持以下三类操作:
1. ADD x y z 加入一个新的点,点的坐标为(x, y, z)。
2. QUERY x y z r 查询在正方体(x, y, z) - (x+r, y+r, z+r)内部的点的数目。
3. CANCEL 撤销最近的一次ADD操作。
其中x, y, z, r均为给出的整数。QUERY操作中,(x, y, z)为正方体的一个顶点的坐标,r为正方体的边长。在正方体边界上的点也算在正方体内部。
这个问题可能过于困难,所以Theresa并不强迫你实现一个高效的数据结构。然而,你必须对每一次QUERY操作给出正确的答案。
分析
太难了…
只水了15分
根据题意模拟
程序
15分做法
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,q,g,x[100000],y[100000],z[100000];
int main()
{
cin>>n;
for (g=1;g<=n;g++)
cin>>x[g]>>y[g]>>z[g];
g--;
cin>>q;
for (int k=1;k<=q;k++)
{
char s[10];
cin>>s;
if (s[0]=='A')
{
g++;
cin>>x[g]>>y[g]>>z[g];
}
if (s[0]=='Q')
{
int x1,y1,z1,r,ans=0;
cin>>x1>>y1>>z1>>r;
for (int i=1;i<=g;i++)
{
if (x[i]>=x1&&x[i]<=(x1+r)&&y[i]>=y1&&y[i]<=(y1+r)&&z[i]>=z1&&z[i]<=(z1+r))
ans++;
}
cout<<ans<<endl;
}
if (s[0]=='C') g--;
}
return 0;
}
100分做法(标程)
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn = 100005;
const int maxt = 2000005;
struct TPt{
int x, y, z;
};
struct Task{
TPt P; int id, r, type;
};
TPt num[maxn]; Task Q[maxn];
int ans[maxn];
int n, m, ns, as, ts;
void init()
{
scanf("%d", &n); ns = 0;
for (int i = 1; i <= n; i ++){
scanf("%d%d%d", &num[i].x, &num[i].y, &num[i].z); Q[ns].P = num[i]; Q[ns ++].type = 1;
}
scanf("%d", &m); char st[7]; ts = n; as = 0;
for (int i = 1; i <= m; i ++){
scanf("%s", st);
if (st[0] == 'A'){
ts ++; scanf("%d%d%d", &num[ts].x, &num[ts].y, &num[ts].z);
Q[ns].P = num[ts]; Q[ns ++].type = 1;
} else if (st[0] == 'C'){
Q[ns].P = num[ts --]; Q[ns ++].type = -1;
} else if (st[0] == 'Q'){
TPt &t = Q[ns].P; scanf("%d%d%d%d%d", &t.x, &t.y, &t.z, &Q[ns].r);
Q[ns].id = as ++; Q[ns ++].type = 0;
}
}
}
inline bool inside(TPt &a, TPt &b, int d){
return a.x >= b.x && a.x <= b.x + d && a.y >= b.y && a.y <= b.y + d && a.z >= b.z && a.z <= b.z + d;
}
Task cur[maxn << 1]; int cs;
bool cmp(Task a, Task b){
return a.P.x < b.P.x || (a.P.x == b.P.x && b.type > a.type);
}
int Z[maxn], zs;
int T[maxn];//root
int find(int x){//lower_bound(x) in Z
int l = 0, r = zs - 1;
if (x < Z[0]) l = r = -1;
while (l < r){
int mid = (l + r + 1) >> 1;
if (Z[mid] > x) r = mid - 1;
else l = mid;
}
return l + 1;
}
//treap_begin
struct Tnode{
int lc, rc, key, w, c, s;
} tree[maxt];
#define l(t) tree[t].lc
#define r(t) tree[t].rc
#define t(t) tree[t]
#define lowbit(x) ((x) & ((x) ^ ((x) - 1)))
inline int Get(){
static int x = 12131416; x += (x << 2) + 1; return x;
}
void rot_r(int &t)
{
int lt = l(t);
l(t) = r(lt); r(lt) = t;
t(lt).s = t(t).s; t(t).s = t(l(t)).s + t(r(t)).s + t(t).c;
t = lt;
}
void rot_l(int &t)
{
int rt = r(t);
r(t) = l(rt); l(rt) = t;
t(rt).s = t(t).s; t(t).s = t(l(t)).s + t(r(t)).s + t(t).c;
t = rt;
}
void t_add(int &t, int x, int c)
{
if (!t){
t = ++ ts; l(t) = r(t) = 0; t(t).key = x; t(t).w = Get(); t(t).s = t(t).c = c; return;
}
t(t).s += c;
if (x < t(t).key){
t_add(l(t), x, c);
if (t(l(t)).w < t(t).w) rot_r(t);
} else {
t_add(r(t), x, c);
if (t(r(t)).w < t(t).w) rot_l(t);
}
}
int t_chk(int &t, int x)
{
if (!t) return 0;
if (x < t(t).key) return t_chk(l(t), x);
return t_chk(r(t), x) + t(t).c + t(l(t)).s;
}
//treap_end
void Add(int z, int y, int det)
{
for (int i = z; i <= zs; i += lowbit(i)) t_add(T[i], y, det);
}
int Chk(int z, int y, int r)
{
int ret = 0;
for (int i = z; i; i -= lowbit(i))
ret += t_chk(T[i], y + r) - t_chk(T[i], y - 1);
return ret;
}
void merge()
{
sort(cur, cur + cs, cmp);
zs = 0;
for (int i = 0; i < cs; i ++) if (cur[i].type < 2)//point
Z[zs ++] = cur[i].P.z;
sort(Z, Z + zs);
int z0 = zs; zs = 0;
for (int i = 0; i < z0; i ++)
if (!i || Z[i] != Z[i-1]) Z[zs ++] = Z[i];
for (int i = 1; i <= zs; i ++) T[i] = 0;
ts = 0;
for (int i = 0; i < cs; i ++){
TPt &p = cur[i].P;
if (cur[i].type < 2){//Add
p.z = find(p.z); Add(p.z, p.y, cur[i].type);
} else {//Query
int rt = find(p.z + cur[i].r), lt = find(p.z - 1); if (lt == rt) continue;
int cnt = Chk(rt, p.y, cur[i].r) - Chk(lt, p.y, cur[i].r);
ans[cur[i].id] += (cur[i].type - 3) * cnt;
}
}
}
void solve(int l, int r)
{
//check if force works
int as = 0, qs = 0;
for (int i = l; i <= r; i ++)
if (Q[i].type == 0) qs ++; else as ++;
if (!qs || !as) return;
if (r - l + 1 <= 500){//few
for (int i = l; i <= r; i ++) if (Q[i].type != 0)
for (int j = i+1; j <= r; j ++)
if (Q[j].type == 0 && inside(Q[i].P, Q[j].P, Q[j].r))
ans[Q[j].id] += Q[i].type;
return;
}
//divide
int mid = (l + r) >> 1;
if (l == 0 && r == ns - 1) mid = n - 1;
solve(l, mid);
solve(mid + 1, r);
//merge
cs = 0;
for (int i = l; i <= mid; i ++)
if (Q[i].type != 0) cur[cs ++] = Q[i];
int c0 = cs;
for (int i = mid+1; i <= r; i ++)
if (Q[i].type == 0){
cur[cs] = Q[i]; cur[cs].P.x --; cur[cs].type = 2; cs ++;
cur[cs] = Q[i]; cur[cs].P.x += cur[cs].r; cur[cs].type = 4; cs ++;
}
if (c0 && cs > c0) merge();
}
void work()
{
solve(0, ns - 1);
}
void print()
{
for (int i = 0; i < as; i ++) printf("%d\n", ans[i]);
}
int main()
{
init();
work();
print();
return 0;
}