\(\text{Problem}\)

标准四维偏序

带修改(加和删除)和询问的三维空间正方体内部(包括边上)的点的数目

\(\text{Analysis}\)

打法很多,\(\text{cdq}\) 套 \(\text{cdq}\) 加上树状数组处理或者 \(\text{cdq}\) 套树套树(如树状数组套线段树)等方法都可以

\(\text{K-D tree}\) 的 \(O(n^{1.75})\) 看起来不怎行,但可以过

当然是在开 \(O\) 的情况下

个人选择了 \(\text{cdq}\) 套树状数组套线段树(离散化节省空间)

\(\text{Code}\)

#pragma GCC optimize(3)
#pragma GCC optimize("inline")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse3","sse2","sse")
#pragma GCC diagnostic error "-std=c++14"
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#pragma GCC optimize("fast-math","unroll-loops","no-stack-protector","inline")
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int N = 1e5 + 5, INF = 0x3f3f3f3f;
int n, m, ans[N * 2], tot, top, My, Mz, bz[N * 2]; inline void read(int &x)
{
x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();
} struct node{
int ty, x, y, z, v, id;
}Q[N * 2], st[N], Q1[N * 2]; int Y[N * 2], Z[N * 2];
inline void lisan()
{
for(register int i = 1; i <= tot; i++)
{
Y[++Y[0]] = Q[i].y;
if (!Q[i].ty) Y[++Y[0]] = Q[i].y - Q[i].v - 1;
}
sort(Y + 1, Y + Y[0] + 1);
My = unique(Y + 1, Y + Y[0] + 1) - Y - 1; for(register int i = 1; i <= tot; i++)
{
Z[++Z[0]] = Q[i].z;
if (!Q[i].ty) Z[++Z[0]] = Q[i].z - Q[i].v;
}
sort(Z + 1, Z + Z[0] + 1);
Mz = unique(Z + 1, Z + Z[0] + 1) - Z - 1;
}
inline int findY(int y)
{
int l = 1, r = My, mid, ret = 1;
while (l <= r)
{
mid = (l + r) >> 1;
if (Y[mid] <= y) ret = mid, l = mid + 1;
else r = mid - 1;
}
return ret;
}
inline int findZ(int z)
{
int l = 1, r = Mz, mid, ret = 1;
while (l <= r)
{
mid = (l + r) >> 1;
if (Z[mid] <= z) ret = mid, l = mid + 1;
else r = mid - 1;
}
return ret;
} struct SegTree{
int rt[N * 2], ls[N * 289], rs[N * 289], sum[N * 289], size;
void update_D2(int &p, int l, int r, int z, int v)
{
if (!p) p = ++size, ls[p] = rs[p] = sum[p] = 0;
sum[p] += v;
if (l == r) return;
int mid = (l + r) >> 1;
if (z <= mid) update_D2(ls[p], l, mid, z, v);
else update_D2(rs[p], mid + 1, r, z, v);
}
int query_D2(int p, int l, int r, int z0, int z1)
{
if (!p) return 0;
if (z0 <= l && r <= z1) return sum[p];
int mid = (l + r) >> 1, res = 0;
if (z0 <= mid) res = query_D2(ls[p], l, mid, z0, z1);
if (z1 > mid) res += query_D2(rs[p], mid + 1, r, z0, z1);
return res;
}
}ST; struct BIT{
inline int lowbit(int x){return x & (-x);}
inline void clear(int y){for(int i = findY(y); i <= My && ST.rt[i]; i += lowbit(i)) ST.rt[i] = 0;}
inline void update_D1(int y, int z, int v)
{
if (!y) return;
y = findY(y), z = findZ(z);
for(register int i = y; i <= My; i += lowbit(i)) ST.update_D2(ST.rt[i], 1, Mz, z, v);
}
inline int query(int y0, int y1, int z0, int z1)
{
y0 = findY(y0 - 1), y1 = findY(y1), z0 = findZ(z0), z1 = findZ(z1);
return query_D1(y1, z0, z1) - query_D1(y0, z0, z1);
}
inline int query_D1(int y, int z0, int z1)
{
if (!y) return 0;
int res = 0;
for(register int i = y; i; i -= lowbit(i)) res += ST.query_D2(ST.rt[i], 1, Mz, z0, z1);
return res;
}
}T; void cdq(int l, int r)
{
if (l == r) return;
int mid = (l + r) >> 1;
cdq(l, mid), cdq(mid + 1, r);
int i = l, j = mid + 1, k = l - 1;
while (i <= mid && j <= r)
if (Q[i].x <= Q[j].x)
{
if (Q[i].ty) T.update_D1(Q[i].y, Q[i].z, Q[i].v);
Q1[++k] = Q[i++];
}
else{
if (!Q[j].ty)
bz[Q[j].id] = 1, ans[Q[j].id] += T.query(Q[j].y - Q[j].v, Q[j].y, Q[j].z - Q[j].v, Q[j].z);
Q1[++k] = Q[j++];
}
while (i <= mid)
{
if (Q[i].ty) T.update_D1(Q[i].y, Q[i].z, Q[i].v);
Q1[++k] = Q[i++];
}
while (j <= r)
{
if (!Q[j].ty)
bz[Q[j].id] = 1, ans[Q[j].id] += T.query(Q[j].y - Q[j].v, Q[j].y, Q[j].z - Q[j].v, Q[j].z);
Q1[++k] = Q[j++];
}
for(i = l; i <= mid; i++)
if (Q[i].ty && Q[i].y) T.clear(Q[i].y);
ST.size = 0;
for(i = l; i <= r; i++) Q[i] = Q1[i];
} int main()
{
read(n);
for(int i = 1, x, y, z; i <= n; i++) read(x), read(y), read(z), Q[++tot] = node{1, ++x, ++y, ++z, 1};
read(m);
char op[10];
for(int i = 1, x, y, z, v; i <= m; i++)
{
scanf("%s", op);
if (op[0] == 'A') read(x), read(y), read(z), Q[++tot] = node{1, ++x, ++y, ++z, 1}, st[++top] = Q[tot];
else if (op[0] == 'Q') read(x), read(y), read(z), read(v), x = x + 1 + v, y = y + 1 + v, z = z + 1 + v,
Q[++tot] = node{0, x, y, z, v, i}, Q[++tot] = node{0, x - v - 1, y, z, v, i + m};
else Q[++tot] = st[top--], Q[tot].v = -1;
}
lisan();
cdq(1, tot);
for(int i = 1; i <= m; i++)
if (bz[i]) printf("%d\n", ans[i] - ans[i + m]);
}

JZOJ 3304. Theresa与数据结构的更多相关文章

  1. BZOJ3290 : Theresa与数据结构

    CANCEL操作可以看作删点,X坐标可以离散化 将询问按Z坐标差分,转化成两个求Z<=某个数的和的询问 将操作CDQ分治 每次将前一半的修改.后一半的查询按照Z坐标排序 然后扫描线,每到一个询问 ...

  2. 【kd-tree】bzoj3290 Theresa与数据结构

    离线所有操作,对所有可能存在的点建立kd-tree,add相当于权值+1,cancel相当于权值-1. 修改操作要记录kd-tree上每个点的fa,从底向上地进行修改. 优化:若一个矩形框的sumv= ...

  3. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  4. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  5. 一起学 Java(三) 集合框架、数据结构、泛型

    一.Java 集合框架 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常形成一个 ...

  6. 深入浅出Redis-redis底层数据结构(上)

    1.概述 相信使用过Redis 的各位同学都很清楚,Redis 是一个基于键值对(key-value)的分布式存储系统,与Memcached类似,却优于Memcached的一个高性能的key-valu ...

  7. 算法与数据结构(十五) 归并排序(Swift 3.0版)

    上篇博客我们主要聊了堆排序的相关内容,本篇博客,我们就来聊一下归并排序的相关内容.归并排序主要用了分治法的思想,在归并排序中,将我们需要排序的数组进行拆分,将其拆分的足够小.当拆分的数组中只有一个元素 ...

  8. 算法与数据结构(十三) 冒泡排序、插入排序、希尔排序、选择排序(Swift3.0版)

    本篇博客中的代码实现依然采用Swift3.0来实现.在前几篇博客连续的介绍了关于查找的相关内容, 大约包括线性数据结构的顺序查找.折半查找.插值查找.Fibonacci查找,还包括数结构的二叉排序树以 ...

  9. 算法与数据结构(九) 查找表的顺序查找、折半查找、插值查找以及Fibonacci查找

    今天这篇博客就聊聊几种常见的查找算法,当然本篇博客只是涉及了部分查找算法,接下来的几篇博客中都将会介绍关于查找的相关内容.本篇博客主要介绍查找表的顺序查找.折半查找.插值查找以及Fibonacci查找 ...

  10. 算法与数据结构(八) AOV网的关键路径

    上篇博客我们介绍了AOV网的拓扑序列,请参考<数据结构(七) AOV网的拓扑排序(Swift面向对象版)>.拓扑序列中包括项目的每个结点,沿着拓扑序列将项目进行下去是肯定可以将项目完成的, ...

随机推荐

  1. 斐波那契散列算法和hashMap实践

    斐波那契散列和hashMap实践 适合的场景:抽奖(游戏.轮盘.活动促销等等) 如果有不对的地方,欢迎指正! HashMap实现数据散列: 配置项目,引入pom.xml: <dependency ...

  2. vulnhub靶场之HACK ME PLEASE

    准备: 攻击机:虚拟机kali.本机win10. 靶机:HACK ME PLEASE,下载地址:https://download.vulnhub.com/hackmeplease/Hack_Me_Pl ...

  3. Kafka教程(二)API开发-生产者、消费者、topic

    一.地址 1.实时更新的思维导图 https://www.mubucm.com/doc/4uqlpedefuj 2.图片 二.具体内容   5.producer生产者   demo   发送pro.s ...

  4. 3.7:基于Weka的K-means聚类的算法示例

    〇.目标 1.使用Weka平台,并在该平台使用数据导入.可视化等基本操作: 2.对K-means算法的不同初始k值进行比较,对比结果得出结论. 一.打开Weka3.8并导入数据 二.导入数据 三.Si ...

  5. 【每日一题】【判断栈是否为空的方法】2022年1月9日-NC76 用两个栈实现队列的出队入队【入队简单】

    描述用两个栈来实现一个队列,使用n个元素来完成 n 次在队列尾部插入整数(push)和n次在队列头部删除整数(pop)的功能. 队列中的元素为int类型.保证操作合法,即保证pop操作时队列内已有元素 ...

  6. Python异步爬虫(aiohttp版)

    异步协程不太了解的话可以去看我上篇博客:https://www.cnblogs.com/Red-Sun/p/16934843.html PS:本博客是个人笔记分享,不需要扫码加群或必须关注什么的(如果 ...

  7. 记录一次缓存引起的线上BUG

    背景 有一个需求大概是这样的,为了提高推荐系统的性能,需要本来从A服务获取的帖子信息,改为从Redis里面重新读取 Redis里面没有存帖子的所有信息,只存储了推荐系统必要的字段 大概是这样的: 至于 ...

  8. 中国风?古典系?AI中文绘图创作尝鲜!⛵

    作者:韩信子@ShowMeAI 深度学习实战系列:https://www.showmeai.tech/tutorials/42 本文地址:https://www.showmeai.tech/artic ...

  9. Linux基础:ssh与scp

    登陆 登陆服务器 ssh user@hostname user: 用户名 hostname :IP地址或域名 第一次登陆会提示 The authenticity of host '123.57.47. ...

  10. BST查找结构与折半查找方法的实现与实验比较

    简介 作业:查找结构与排序方法 作业题目: BST 查找结构与折半查找方法的实现与实验比较 要求编写程序实现 BST 存储结构的建立(插入).删除.查找和排序算法: 实现折半查找算法:比较 BST 查 ...