Distance(2019年牛客多校第八场D题+CDQ+树状数组)
题目链接
思路
这个题在\(BZOJ\)上有个二维平面的版本(\(BZOJ2716\)天使玩偶),不过是权限题因此就不附带链接了,我也只是在算法进阶指南上看到过,那个题的写法是\(CDQ\),然后比赛开始半个小时我就开始写\(CDQ\),\(T\)了之后冷静分析发现复杂度我少算了个\(log\),\(CDQ\)写这题的复杂度是\(nlog^3(n)\),然后就没思路了。
赛后看\(qls\)说用三维\(bit\)可以过后试了一下\(T\)了,然后发现\(qls\)的代码当时跑了\(937ms\)应该是卡过去的,感觉是\(vector\)常数大,但是想不出除\(vector\)的其他动态开全局数组大小的方法,最后疯狂交在\(T\)了一页后成功卡过去了,下面贴一下三维\(bit\)的代码和\(CDQ\)写法(对拍了很久貌似没问题,就当过了吧~)的代码。
这两份代码的主体思路就是拆绝对值符号,然后查询时(拿\(x_1\leq x2,y_1\leq y2,z_1\leq z_2\)举例,下标为\(2\)的是查询的点)\(|x_2-x_1|+|y_2-y_1|+|z_2-z_1|=(x_2+y_2+z_2)-(x_1+y_1+z_1)\),然后就是要查询\(x_1+y_1+z_1\)的最大值用树状数组维护即可,其他情况分别移动坐标即可。
update:发现题解里面贴的那份代码的三维\(bit\)写法贼牛逼,贴的代码就改成看了那个队的代码之后写的了。
代码
//三维bit
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 800000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int n, m, h, q, op, x, y, z;
struct BIT {
int a[maxn];
int gethash(int x, int y, int z) {
return x * h * m + y * h + z;
}
void init() {
for(int i = 0; i <= n; ++i) {
for(int j = 0; j <= m; ++j) {
for(int k = 0; k <= h; ++k) {
a[gethash(i, j, k)] = 0;
}
}
}
}
void update(int x, int y, int z) {
for(int i = x; i <= n; i += lowbit(i)) {
for(int j = y; j <= m; j += lowbit(j)) {
for(int k = z; k <= h; k += lowbit(k)) {
int num = gethash(i, j, k);
a[num] = max(a[num], x + y + z);
}
}
}
}
int query(int x, int y, int z) {
int ans = 0;
for(int i = x; i > 0; i -= lowbit(i)) {
for(int j = y; j > 0; j -= lowbit(j)) {
for(int k = z; k > 0; k -= lowbit(k)) {
ans = max(ans, a[gethash(i, j, k)]);
}
}
}
if(ans == 0) return inf;
return x + y + z - ans;
}
}bit[8];
int main() {
scanf("%d%d%d%d", &n, &m, &h, &q);
n += 1, m += 1, h += 1;
for(int i = 0; i < 8; ++i) bit[i].init();
for(int i = 1; i <= q; ++i) {
scanf("%d%d%d%d", &op, &x, &y, &z);
if(op == 1) {
bit[1].update(x, y, z);
bit[2].update(x, y, h - z);
bit[3].update(x, m - y, z);
bit[4].update(n - x, y, z);
bit[5].update(n - x, m - y, z);
bit[6].update(n - x, y, h - z);
bit[7].update(x, m - y, h - z);
bit[0].update(n - x, m - y, h - z);
} else {
int ans = inf;
ans = min(ans, bit[1].query(x, y, z));
ans = min(ans, bit[2].query(x, y, h - z));
ans = min(ans, bit[3].query(x, m - y, z));
ans = min(ans, bit[4].query(n - x, y, z));
ans = min(ans, bit[5].query(n - x, m - y, z));
ans = min(ans, bit[6].query(n - x, y, h - z));
ans = min(ans, bit[7].query(x, m - y, h - z));
ans = min(ans, bit[0].query(n - x, m - y, h - z));
printf("%d\n", ans);
}
}
return 0;
}
//CDQ
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 100001;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int n, m, h, q, op, x, y, z;
int tree[maxn], ans[maxn];
struct node {
int id, x, y, z, op, val, flag;
bool operator < (const node& a) const {
return id < a.id;
}
}a[maxn], tmp[maxn], pp[maxn];
void add(int x, int val) {
while(x <= h) {
tree[x] = max(tree[x], val);
x += lowbit(x);
}
}
int query(int x) {
int ans = 0;
while(x) {
ans = max(ans, tree[x]);
x -= lowbit(x);
}
if(ans == 0) ans = -inf;
return ans;
}
void del(int x) {
while(x <= h + 1) {
tree[x] = 0;
x += lowbit(x);
}
}
void cdq2(int l, int r) {
if(l == r) return;
int mid = (l + r) >> 1;
cdq2(l, mid), cdq2(mid + 1, r);
int ls = l, rs = mid + 1, cnt = l;
for(; rs <= r; ++rs) {
for(; ls <= mid && tmp[ls].y <= tmp[rs].y; ++ls) {
if(tmp[ls].op == 1 && tmp[ls].flag) {
add(tmp[ls].z, tmp[ls].val);
}
}
if(!tmp[rs].flag && tmp[rs].op == 2) ans[tmp[rs].id] = min(ans[tmp[rs].id], tmp[rs].val - query(tmp[rs].z));
}
--ls;
while(ls >= l) {
if(tmp[ls].op == 1 && tmp[ls].flag) {
del(tmp[ls].z);
}
--ls;
}
ls = l, rs = mid + 1;
while(ls <= mid && rs <= r) {
if(tmp[ls].y < tmp[rs].y) {
pp[cnt++] = tmp[ls++];
} else if(tmp[ls].y > tmp[rs].y) {
pp[cnt++] = tmp[rs++];
} else if(tmp[ls].z <= tmp[rs].z) {
pp[cnt++] = tmp[ls++];
} else {
pp[cnt++] = tmp[rs++];
}
}
while(ls <= mid) pp[cnt++] = tmp[ls++];
while(rs <= r) pp[cnt++] = tmp[rs++];
for(int i = l; i <= r; ++i) tmp[i] = pp[i];
}
void cdq1(int l, int r) {
if(l == r) return;
int mid = (l + r) >> 1;
cdq1(l, mid), cdq1(mid + 1, r);
int ls = l, rs = mid + 1, cnt = l;
while(ls <= mid && rs <= r) {
if(a[ls].x < a[rs].x) {
tmp[cnt] = a[ls++];
tmp[cnt++].flag = 1;
} else if(a[ls].x > a[rs].x) {
tmp[cnt] = a[rs++];
tmp[cnt++].flag = 0;
} else if(a[ls].y < a[rs].y) {
tmp[cnt] = a[ls++];
tmp[cnt++].flag = 1;
} else if(a[ls].y > a[rs].y) {
tmp[cnt] = a[rs++];
tmp[cnt++].flag = 0;
} else if(a[ls].z <= a[rs].z) {
tmp[cnt] = a[ls++];
tmp[cnt++].flag = 1;
} else {
tmp[cnt] = a[rs++];
tmp[cnt++].flag = 0;
}
}
while(ls <= mid) {
tmp[cnt] = a[ls++];
tmp[cnt++].flag = 1;
}
while(rs <= r) {
tmp[cnt] = a[rs++];
tmp[cnt++].flag = 0;
}
for(int i = l; i <= r; ++i) a[i] = tmp[i];
cdq2(l, r);
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%d%d%d%d", &n, &m, &h, &q);
n += 1, m += 1, h += 1;
for(int i = 1; i <= q; ++i) {
scanf("%d%d%d%d", &op, &x, &y, &z);
a[i] = {i, x, y, z, op, 0, 0};
}
//x,y,z
for(int i = 1; i <= q; ++i) {
ans[i] = inf;
a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
}
cdq1(1, q);
//x,y,-z
for(int i = 1; i <= q; ++i) {
a[i].z = h - a[i].z;
a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
}
sort(a + 1, a + q + 1);
cdq1(1, q);
//x,-y,z
for(int i = 1; i <= q; ++i) {
a[i].z = h - a[i].z;
a[i].y = m - a[i].y;
a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
}
sort(a + 1, a + q + 1);
cdq1(1, q);
//-x,y,z
for(int i = 1; i <= q; ++i) {
a[i].y = m - a[i].y;
a[i].x = n - a[i].x;
a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
}
sort(a + 1, a + q + 1);
cdq1(1, q);
//-x,-y,z
for(int i = 1; i <= q; ++i) {
a[i].y = m - a[i].y;
a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
}
sort(a + 1, a + q + 1);
cdq1(1, q);
//-x,y,-z
for(int i = 1; i <= q; ++i) {
a[i].y = m - a[i].y;
a[i].z = h - a[i].z;
a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
}
sort(a + 1, a + q + 1);
cdq1(1, q);
//x,-y,-z
for(int i = 1; i <= q; ++i) {
a[i].x = n - a[i].x;
a[i].y = m - a[i].y;
a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
}
sort(a + 1, a + q + 1);
cdq1(1, q);
//-x,-y,-z
for(int i = 1; i <= q; ++i) {
a[i].x = n - a[i].x;
a[i].val = a[i].x + a[i].y + a[i].z, a[i].flag = 0;
}
sort(a + 1, a + q + 1);
cdq1(1, q);
sort(a + 1, a + q + 1);
for(int i = 1; i <= q; ++i) {
if(a[i].op == 2) {
printf("%d\n", ans[i]);
}
}
return 0;
}
Distance(2019年牛客多校第八场D题+CDQ+树状数组)的更多相关文章
- Explorer(2019年牛客多校第八场E题+线段树+可撤销并查集)
题目链接 传送门 题意 给你一张无向图,每条边\(u_i,v_i\)的权值范围为\([L_i,R_i]\),要经过这条边的条件是你的容量要在\([L_i,R_i]\),现在问你你有多少种容量使得你可以 ...
- 2019牛客多校第七场 F Energy stones 树状数组+算贡献转化模拟
Energy stones 题意 有n块石头,每块有初始能量E[i],每秒石头会增长能量L[i],石头的能量上限是C[i],现有m次时刻,每次会把[s[i],t[i]]的石头的能量吸干,问最后得到了多 ...
- 2019牛客多校第八场 F题 Flowers 计算几何+线段树
2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...
- 2020牛客多校第八场K题
__int128(例题:2020牛客多校第八场K题) 题意: 有n道菜,第i道菜的利润为\(a_i\),且有\(b_i\)盘.你要按照下列要求给顾客上菜. 1.每位顾客至少有一道菜 2.给顾客上菜时, ...
- 2019年牛客多校第四场 B题xor(线段树+线性基交)
题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...
- Palindrome Mouse(2019年牛客多校第六场C题+回文树+树状数组)
目录 题目链接 题意 思路 代码 题目链接 传送门 题意 问\(s\)串中所有本质不同的回文子串中有多少对回文子串满足\(a\)是\(b\)的子串. 思路 参考代码:传送门 本质不同的回文子串肯定是要 ...
- generator 1(2019年牛客多校第五场B题+十进制矩阵快速幂)
目录 题目链接 思路 代码 题目链接 传送门 思路 十进制矩阵快速幂. 代码 #include <set> #include <map> #include <deque& ...
- Find the median(2019年牛客多校第七场E题+左闭右开线段树)
题目链接 传送门 题意 每次往集合里面添加一段连续区间的数,然后询问当前集合内的中位数. 思路 思路很好想,但是卡内存. 当时写的动态开点线段树没卡过去,赛后机房大佬用动态开点过了,\(tql\). ...
- 2019年牛客多校第三场 F题Planting Trees(单调队列)
题目链接 传送门 题意 给你一个\(n\times n\)的矩形,要你求出一个面积最大的矩形使得这个矩形内的最大值减最小值小于等于\(M\). 思路 单调队列滚动窗口. 比赛的时候我的想法是先枚举长度 ...
随机推荐
- Java的策略和保护域
参考文章: (1)java之jvm学习笔记十(策略和保护域) https://blog.csdn.net/yfqnihao/article/details/8271415
- 2018-2019-2 网络对抗技术 20165230 Exp7 网络欺诈防范
实验目的 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法. 实验内容 简单应用SET工具建立冒名网站 ettercap DNS spoof 结合应用两种技术,用DNS sp ...
- 如何使用 Django中的 get_queryset, get_context_data和 get_object 等方法
原文: https://blog.csdn.net/HH2030/article/details/80994274
- 《Linux就该这么学》培训笔记_ch01_部署虚拟环境安装Linux系统
<Linux就该这么学>培训笔记_ch01_部署虚拟环境安装Linux系统 文章最后会post上书本的笔记照片. 文章主要内容: 在虚拟机中安装红帽RHEL7系统 在Linux系统中找回r ...
- 你不知道的js——数组 join
你可能对使用数组的 join 方法已经轻车熟路,但你也许不知道: 10.If element0 is undefined or null, let R be the empty String; oth ...
- [转帖]分布式一致性协议介绍(Paxos、Raft)
分布式一致性协议介绍(Paxos.Raft) https://www.cnblogs.com/hugb/p/8955505.html 两阶段提交 Two-phase Commit(2PC):保证一个 ...
- Linux低延迟服务器系统调优
最近做了一些系统和网络调优相关的测试,达到了期望的效果,有些感悟.同时,我也发现知乎上对Linux服务器低延迟技术的讨论比较欠缺(满嘴高并发现象):或者对现今cpu + 网卡的低延迟潜力认识不足(动辄 ...
- MyEclipse部署外部引用的jar到web-inf的lib目录下
在用MyEclipse开发java web项目的时候,引入了外部jar,都是以library的形式存在左边的explore中的,调试没有问题,但是部署之后呢,经常遇到个非常头疼的问题就是,这些jar不 ...
- HTML 引用大全
路径logo <link rel="icon" href="../framework7-4.4.10/kitchen-sink/core/img/ztjs.png& ...
- 2019 东方网java面试笔试题 (含面试题解析)
本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.东方网等公司offer,岗位是Java后端开发,因为发展原因最终选择去了东方网,入职一年时间了,也成为了面试官 ...