首页 > 其他分享 >SS241106B. 即便看不到未来

SS241106B. 即便看不到未来

时间:2024-11-06 19:19:03浏览次数:1  
标签:ch 即便 SS241106B int 约束 一维 看不到 cpp 合法

SS241106B. 即便看不到未来

题意

给你一个无限大的三维空间,有 \(n\) 个点,每个点的坐标是 \((x_i,y_i,z_i)\),满足 \(n\le 5\times 10^5,|x_i|,|y_i|,|z_i| \le 10^9\)。你从 \((-inf,-inf,-inf)\) 出发,可以向三个正方向走。

定义攻击距离 \(k\),若你在 \((x,y,z)\),对于 \(\max\{ |x-x'|, |y-y'|, |z-z'| \}\) 的所有 \((x',y',z')\) 是可以攻击到的。问最小化的 \(k\) 使得你可以走一次攻击完所有点。

思路

介绍一个如果你想明白了就很好写的二分答案做法,不过代码可能稍长。

感觉很容易想到二分答案啊,然后一直假,而且细节太多,还需要丰富的想象力,赛场上调了 \(3h+\) 都没调出来。。。

显然二分答案 \(k\),考虑如何判断 \(k\) 是否合法。

相当于每个点 \((x_i,y_i,z_i)\) 存在一个左下角 \((x_i-k,y_i-k,z_i-k)\),右上角 \((x_i+k,y_i+k,z_i+k)\) 的正方体,你需要判断是否存在一条路径,满足坐标只加不减,经过所有正方体。

思考历程:
  1. 扫描线?

考虑先做二维的问题,可以扫描线 + 贪心做。一共有 \(O(n)\) 个正方形的顶点,建立右边为 \(x\) 轴正方向,上面为 \(y\) 轴正方向的坐标系,按照 \(x\) 坐标扫,如果一个正方形消失了,就走到这个正方形的最下面我能到达的那一行,然后清除一下途中经过的其他正方形。如果一个正方形消失的时候,我在它上边界的上面,我到达不了它,就返回不合法。

考虑三维的问题,建立上面为时间 \(x\) 正方向,右边为 \(y\) 轴正方向,前面为 \(z\) 轴正方向的三维坐标系。一开始我们在下左后角。然后每次正方形消失就贪心地走到最左后的地方。嗯?怎么感觉正确性是真的?好像真的是?但是最重要的问题是扫了一维,还剩两维怎么线段树维护啊?有这种科技吗?

\(\quad\) 2.1 开启观察模式

发现二维的问题,其实可以转化成,如果存在 \(i,j\),使得 \(i\) 的右下角在 \(j\) 的左上角的严格左上方,就是不合法的,否则一定合法,可以感性理解。

那么观察三维的问题,发现不那么好观察。

一个错误的结论是,如果存在 \(i,j\),使得 \(i\) 的第 \(p\) 维的下边界严格大于 \(j\) 的第 \(p\) 维的上边界,且 \(j\) 的第 \(q\) 维的下边界严格大于 \(i\) 的第 \(q\) 维的上边界,就返回不合法,否则合法。

这么做时间可以做到单次 check \(O(n)\) 的,可惜正确性错误。

\(\quad\) 2.2 错误之处

直接讲刚刚结论的错误之处,在于可能存在 \(i,j,k\)(此 \(k\) 非彼 \(k\))使得 \(j\) 的 \(x\) 维严格大于 \(i\),\(k\) 的 \(y\) 维严格大于 \(j\),\(x\) 的 \(z\) 维严格大于 \(k\)(这里【严格大于】指的是前者的下边界严格大于后者的上边界),即 \(j\) 在 \(i\) 上面偏后偏左,\(k\) 在 \(j\) 右边偏后偏左偏下,\(i\) 又在 \(k\) 前面。

可以通过这个观察发现,这是一个 \(i\to j\to k\to i\) 的环,可以观察得到下面的结论,然后就可以做了,当然有另一种更为直接的观察方法。

  1. 小样例启动!

实际上赛时我选择直接抛弃了刚刚的结论,因为我无法想出结论的错误之处并改正。但是在写暴力代码之前先尝试手模小样例的过程中得到了启发,我写了一些随便的数据,并试图排序一个合法的经过顺序,来得到样例输出。然后发现可以根据依赖关系判环来判定是否合法。

我们发现对于某一维,如果 \(i\) 的上界严格小于 \(j\) 的下界,即 \(p_i + 2k < p_j\)(对于维 \(p\)),那么必须先经过 \(i\) 再经过 \(j\),否则你先走到 \(j\) 你就无法进入正方体 \(i\) 了。

这样就有了若干个约束条件,然后你感觉如果满足所有约束条件,就一定可以保证答案合法了,事实上这个结论是正确的。很好证明,因为对于每一维剩下没有约束的点,任意两个点在这一维上都是有交的,那么你直接待在这个交的区域不走就可以了。

对 \(x,y,z\) 三维分别排序,对于其中一维 \(p\),排名第 \(i\) 的点的约束就是一段排名的前缀对应点必须在它之前经过。我们把关于第 \(p\) 维的约束条件叫做边 \(P\)。

求前缀的长度可以双指针,因为前缀长度随枚举右指针是递增的。

考虑无解(即有环)的情况有哪些。

  1. 边 \((X,Y),(Y,Z),(Z,X)\) 形成的环。
  2. 边 \((X,Y,Z),(X,Z,Y)\) 形成的环。

注意这里的点对是有序的。不过由于是环所以只判以上五种情况就可以了。

对于第 \(1\) 种,\((P_1,P_2)\),其实就是在 \(p_2\) 这一维里,要先经过 \(v\) 再经过 \(u\),而在 \(p_1\) 这一维里约束了先经过 \(u\) 再经过 \(v\)。那么可以在做 \(p_1\) 这一维的时候统计约束在 \(i\) 之前的那段前缀的点中,在 \(p_1\) 这一维的坐标最大值,找 \(u\) 在 \(p_2\) 维的对应约束前缀的时候,看看这段前缀及其约束的 \(p_1\) 坐标最大值是不是严格大于 \(p_u+2k\) 就可以了。简单来讲就是对每个点维护约束必须在其之前经过的点的 \(p_1\) 坐标最大值,对 \(p_2\) 维判断约束必须在其之前经过的点是否存在矛盾。

对于第二种,也是类似的,维护每个点,其约束的所有点(指约束了必须在其之前的所有点)的 \(x\) 坐标最大值,然后判断是否矛盾。

感觉讲不清楚?

时间复杂度 \(O(n\log n + n\log V)\)。

code

这结论太难猜了,我只能死命地对拍和手模,有没有什么高效的方法呢?也许需要更加丰富的经验?

这题我一共写了 \(8\) 个 cpp 文件,他们分别是:checker.cpp diffcheck.cpp duipai.cpp hunt.cpp hunt2.cpp huntbaoli.cpp shuju.cpp tmp.cpp,我真是有耐心啊!其实心态崩了

喜获目前最慢解和最长解。

#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
namespace cute_chtholly {
	constexpr int N=5e5+7,V=2e9;
	void _max(int &a,int b) { a=max(a,b); }
	#define isdigit(x) (x>='0'&&x<='9')
	#define gc getchar_unlocked
	#define pc putchar_unlocked
	template <typename T>
	void read(T &x) {
		char ch=gc();
		x=0;
		T fl=1;
		for(;!isdigit(ch);ch=gc()) if(ch=='-') fl=-1;
		for(;isdigit(ch);ch=gc()) x=(x<<3)+(x<<1)+(ch^48);
		x=x*fl;
	}
	template <typename T>
	void write (T x,char ch) {
		static int st[40];
		int top=0;
		do {
			st[top++]=x%10;
			x/=10;
		}while(x);
		while(top) pc(st[--top]^48);
		pc(ch);
	}
	int n;
	int a[3][N],rrk[3][N];
	int rk[3][N];
	int l=0,r=1e9;
	int K;
	bool cmpx(int p,int q) { return a[0][p] < a[0][q]; }
	bool cmpy(int p,int q) { return a[1][p] < a[1][q]; }
	bool cmpz(int p,int q) { return a[2][p] < a[2][q]; }
	int mxx[3][N];
	int mx[3][N],_mxx[3][N];
	bool check() {
		int k=K<<1;
		memcpy(mxx,_mxx,sizeof(mxx));
		int it=0;
		rep(i,1,n) _max(mxx[0][i],mxx[0][i-1]);
		rep(i,1,n) {
			int u=rk[0][i];
			while(a[0][rk[0][it+1]]+k < a[0][u]) ++it;
			if(a[2][u]+k < mx[0][it]) return 0;
			_max(mxx[1][rrk[1][u]],mxx[0][it]);
			_max(mxx[2][rrk[2][u]],mxx[0][it]);
		}
		it=0;
		rep(i,1,n) _max(mxx[1][i],mxx[1][i-1]);
		rep(i,1,n) {
			int u=rk[1][i];
			while(a[1][rk[1][it+1]]+k < a[1][u]) ++it;
			if(a[0][u]+k < mx[1][it]) return 0;
			_max(mxx[2][rrk[2][u]],mxx[1][it]);
		}
		it=0;
		rep(i,1,n) _max(mxx[2][i],mxx[2][i-1]);
		rep(i,1,n) {
			int u=rk[2][i];
			while(a[2][rk[2][it+1]]+k < a[2][u]) ++it;
			if(a[1][u]+k < mx[2][it]) return 0;
			if(a[0][u]+k < mxx[2][it]) return 0;
			_max(mxx[1][rrk[1][u]],mxx[2][it]);
		}
		it=0;
		rep(i,1,n) _max(mxx[1][i],mxx[1][i-1]);
		rep(i,1,n) {
			int u=rk[1][i];
			while(a[1][rk[1][it+1]]+k < a[1][u]) ++it;
			if(a[0][u]+k < mxx[1][it]) return 0;
		}
		return 1;
	}
	void main() {
		read(n);
		rep(i,1,n) read(a[0][i]),read(a[1][i]),read(a[2][i]), rk[0][i]=rk[1][i]=rk[2][i]=i;
		sort(rk[0]+1,rk[0]+n+1,cmpx);
		sort(rk[1]+1,rk[1]+n+1,cmpy);
		sort(rk[2]+1,rk[2]+n+1,cmpz);
		rep(j,0,2) rep(i,1,n) _mxx[j][i]=a[0][rk[j][i]], rrk[j][rk[j][i]]=i;
		rep(j,0,2) mx[j][0]=_mxx[j][0]=-V;
		rep(i,1,n) mx[0][i]=max(a[2][rk[0][i]],mx[0][i-1]), mx[1][i]=max(a[0][rk[1][i]],mx[1][i-1]), mx[2][i]=max(a[1][rk[2][i]],mx[2][i-1]);
		while(l<r) {
			K=(l+r)>>1;
			if(check()) r=K;
			else l=K+1;
		}
		write(r,'\n');
	}
}
int main() {
	#ifdef LOCAL
	freopen("my.out","w",stdout);
	#else 
	freopen("hunt.in","r",stdin);
	freopen("hunt.out","w",stdout);
	#endif
	cute_chtholly :: main();
}

标签:ch,即便,SS241106B,int,约束,一维,看不到,cpp,合法
From: https://www.cnblogs.com/liyixin0514/p/18530548

相关文章

  • 查看不到 ~$ 前缀的文件
    ~$前缀的文件一般都是隐藏文件win10中查看隐藏文件的方式就可以看到再删除但是今天遇到了个看不见的隐藏文件但是打开cmddir/a还是可以看到这个隐藏文件于是使用命令直接删除该文件DEL"file_path\fileName" /A:H  del命令参数说明/F 强制删除文件。/S ......
  • 递归深拷贝导致浏览器网络请求中看不到响应
    前言:在项目中发现一个奇怪的问题,一个请求在数据量少的时候非常快速,数据量多的时候非常慢,甚至导致浏览器崩溃,在浏览器的网络抓包中看到有返回状态时200,但是响应迟迟没有返回,并且可以看到等待服务器响应时间非常长。排查:一开始是定位在后端问题,因为查询类型为1的时候反应速度非常快......
  • 加拿大GPA低被开除看不到毕业希望怎么办?
    加拿大GPA低被开除看不到毕业希望怎么办?在加拿大留学每年都会有部分学生因GPA低的问题,面临被警告,停学或是被开除的风险。虽然这种情况已经很常见了,但每当事情发生到自己身上时,还是难免手足无措。国内人口众多,高等教育资源有限,所以为了孩子能考上理想的高中或是大学,部分家长都开启了......
  • 为什么git有些commit记录,只有git reflog可以看到,git log看不到?
    文章目录原因分析1.`gitlog`只能显示**可达的**提交2.`gitreflog`记录所有引用的变更常见导致`gitlog`看不到提交的原因1.`gitreset`操作2.`gitrebase`操作3.分支删除4.`gitcommit--amend`5.垃圾回收(GC)*如何恢复`gitlog`看不到的提交?总结......
  • 帝国cms记录用户点击的时间怎么看不到了
    如果你发现帝国CMS中记录用户点击时间的功能失效了,可以按照以下步骤来排查问题:检查数据库:使用数据库管理工具(如phpMyAdmin)连接到帝国CMS使用的数据库。查找存储文章点击数据的数据表,通常这个表的名字可能是 ecms_article 或者其他与你的站点配置相关的表名。检查表结构,确......
  • 【公司搬砖摸鱼神器】领导再也看不到我摸鱼啦!
    【公司搬砖摸鱼神器】领导再也看不到我摸鱼啦!文章目录【公司搬砖摸鱼神器】领导再也看不到我摸鱼啦!介绍电脑开机自启设置感谢和资源获取温馨提示:本篇工具在公众号......
  • RHEL 9中,开机看不到菜单选项,如何解决?
    记一个小方法在使用RHEL9的时候,发现开机的时候没有菜单选项(造成的原因暂未深究),也就无法通过e进入救援模式了,这是有潜在风险的。那么,如何让菜单展示出来呢,还是说,菜单损坏了?后来发现,其实只是timeout设置成了0,只需要修改成非0的数据,就可以让开机后的菜单显现出来那么如何修改了?......
  • 坚果云,文件夹同步冲突、共享文件夹权限提示文件已共享实际查看不到
    一、提示冲突打开注册表1、按下面的路径\HKEYLOCALMACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SyncRootManager\看是否有【Nutstore-临时】开头的项和【Nutstore-通知】开头的项。如果有,删掉这两项就好了。2、重新同步文件夹就可以了二、共享文件夹权......
  • 小白必看的cmd简单代码!(图片看不到的可复制 粘贴到Typroa进行观看)
    打卡cmd的方法直接window加r输入cmd在下方菜单找到window标志,打开输入命令提示符更高级的cmd权限使用:右键命令提示符,点击"以管理员身份运行"一些简单的dos命令(均需英文输入法)(回车步骤省略)1.盘符切换:打开cmd后输入想要切换的磁盘再加上:即可![](C:\Users\直実\Pictures......
  • venv 已激活,但 pip 安装仍然默认进行,并且 python 在源代码中看不到该库
    在终端shell中的vscode中输入“whichpython”显示默认路径:C:\Users\erjan\AppData\Local\Programs\Python\Python311\python.exe(my_venv)但是(my_venv)意味着我的venv处于活动状态,我做了pipinstalltransformers,但下面的代码仍然显示错误-无法看到......