Theresa与数据结构

题目

这是个复杂的世界。人类社会,自然界,还有地球之外的银河……
每一天日出日落,人来人往,步履匆匆。究竟是为什么呢?那支配着一切的至高无上的法则又是否存在呢?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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值