首页 > 其他分享 >题解:洛谷 P10996 【MX-J3-T3】Tuple

题解:洛谷 P10996 【MX-J3-T3】Tuple

时间:2024-09-01 08:54:59浏览次数:2  
标签:map 洛谷 Tuple int 题解 三元组 mp include unordered

原题链接

介绍一种(也许是正解的)卡常做法

先说总体思路:对于每个三元组 \((x,y,z)\),若有一个 \(w\) 满足 \((x,y,w),(x,z,w),(y,z,w)\) 均存在,则找到了一个合法的四元组 \((x,y,z,w)\)。

\(20\ \rm{Pts}\) 做法

如果暴力搜索,在遍历每一个三元组时,每一次都扫描所有的 \(w \in [1,N]\),判断是否存在三元组另需 \(O(M)\),时间复杂度是 \(O(NM^2)\),很明显会超时,应当勉强能得 \(20\) 分。我没打这个,就不贴代码了。

\(80\ \rm{Pts}\) 做法

考虑上述暴力做法的优化空间:

优化 #1

判断三元组是否存在可以不将所有三元组都扫描一遍,直接用一个桶 \(mp[x][y][z]\) 来记录,若存在则为 true。但是很明显,在 \(N \le 2000\) 时,三维数组会爆空间,所以我们就需要使用 unordered_map 作为哈希表来代替这个桶来记录三元组的存在(不用 map 是因为 unordered_map 时间复杂度更低)。

这样就可以 \(O(1)\) 查询三元组存在性,总时间复杂度降至 \(O(NM)\)。

优化 #2

对于 \(w\) 的取值,它首先需要满足三元组 \((x,y,w)\) 存在,所以我们可以记录对于每一对 \((x,y)\),能与其组成三元组的所有 \(w\),在遍历三元组 \((x,y,z)\) 的时候只用判断能和 \((x,y)\) 组成三元组的 \(w\) 就可以了。

总时间复杂度进一步降为 \(O(M)\)。

这样就可以拿 \(80\) 分了。

参考代码:

#include<cstdio>
#include<unordered_map>
#include<vector>
using namespace std;

const int N=2005,M=5e4+5;
int n,m,ans;
unordered_map<int,int> mp[N][N];
vector<int> v[N][N];

struct Peter{
	int x,y,z;
}p[M];

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
		mp[p[i].x][p[i].y][p[i].z]=true;
		v[p[i].x][p[i].y].push_back(p[i].z);
	}
	for(int i=1;i<=m;i++)
	{
		int x=p[i].x,y=p[i].y,z=p[i].z;
		for(int w:v[x][y])
		{
			if(w==z) continue;
			if(mp[x][z][w]&&mp[y][z][w])
				ans++;
		}
	}
	printf("%d\n",ans);
	return 0;
}

\(100\ \rm{Pts}\) 做法

上面之所以时间复杂度已经足够低,但依然无法满分,就是因为根据 unordered_map 的原理,如果试图寻找某一键值对应的数是,该键值不存在,那么它就会新建这个键值,增大占用空间。在极限数据下可能导致 MLE。

对应到上面的代码就是在执行 if(mp[x][z][w]&&mp[y][z][w]) 时,unordered_map 试图查询 mp[x][z][w]mp[y][z][w],但是如果这两个值不存在(以前没有被赋值或访问过),那么它就会在哈希表中加入 mp[x][z][w]mp[y][z][w]unordered_map 优化空间的原理就是没有用到值的就不开空间),造成了不必要的空间开销。

所以我们可以加上一个特判。因为 mp[x][y][z] 存在的前提是:

  • \(x,y\) 同时出现在一个三元组中过;
  • \(y,z\) 同时出现在一个三元组中过;
  • \(x,z\) 同时出现在一个三元组中过。

所以可以再开一个桶 \(tog\),令 \(tog_{x,y}\) 表示 \(x,y\) 在同一个三元组中出现过。

这样,在判断 if(mp[x][z][w] && mp[y][z][w]) 前,先判断 if(tog[x][w] && tog[z][w] && tog[y][w])。如果第二个条件都不满足,第一个条件自然也不可能满足,就可以省去不必要的对 mp[x][z][w]mp[y][z][w] 的访问,避免不必要的空间开销。

参考代码:

#include<cstdio>
#include<unordered_map>
#include<vector>
using namespace std;

const int N=2005,M=5e4+5;
int n,m,ans;
unordered_map<int,unordered_map<int,bool>> mp[N];
bool tog[N][N];
vector<int> v[N][N];

struct Peter{
	int x,y,z;
}p[M];

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
		mp[p[i].x][p[i].y][p[i].z]=true;
		tog[p[i].x][p[i].y]=tog[p[i].x][p[i].z]=tog[p[i].y][p[i].z]=true;
		v[p[i].x][p[i].y].push_back(p[i].z);
	}
	for(int i=1;i<=m;i++)
	{
		int x=p[i].x,y=p[i].y,z=p[i].z;
		for(int w:v[x][y])
		{
			if(w==z) continue;
			if(tog[x][w]&&tog[z][w]&&tog[y][w])
				if(mp[x][z][w]&&mp[y][z][w]) ans++;
		}
	}
	printf("%d\n",ans);
	return 0;
}

所有测试点中最大时间为 \(148ms\),最大空间为 \(182.84MB\),十分优秀,成功卡过。

标签:map,洛谷,Tuple,int,题解,三元组,mp,include,unordered
From: https://www.cnblogs.com/jerrycyx/p/18390999

相关文章

  • 题解:洛谷 P10497 [USACO03Open] Lost Cows
    原题链接思路+算法首先,考虑读入到\(a_i\)时,如果要得到此时的最优解(指所有牛的编号不重不漏地覆盖\([1,i]\)的所有编号),对于第\(i\)头奶牛,因为在它前面有\(a_i\)头奶牛的编号小于它,所以第\(i\)头奶牛的编号应当为\(a_i+1\)。如果有一头新的奶牛\(i+1\)加入到这个......
  • 题解:洛谷 P10878 [JRKSJ R9] 在相思树下 III
    原题链接解析在操作一时,最小值如果在最后一位,其无法更新任何数,会被删除;否则不在最后一位时一定会被其右侧更大的数更新。所以在操作一时,最小值一定会被更新掉。同理,在操作二时,最大值一定会被更新掉。由此,操作一决定了答案的下限,操作二决定了答案的上限。所以可以得出贪心策略......
  • LOJ #6089. 小 Y 的背包计数问题 题解
    Description小Y有一个大小为\(n\)的背包,并且小Y有\(n\)种物品。对于第\(i\)种物品,共有\(i\)个可以使用,并且对于每一个\(i\)物品,体积均为\(i\)。求小Y把该背包装满的方案数为多少,答案对于\(23333333\)取模。定义两种不同的方案为:当且仅当至少存在一种物品的......
  • 学校训练赛的一些题解
    第二十一届宁波大学程序设计竞赛(重现赛链接)C游戏开发部的小游戏(C)赛时并没有写出来,果然dp还得多练)将所有石头视为容量为\(n\)的背包,每堆石头的数量即背包中物品的质量,对于\(a_i\leqf_i\leqb_i\),由于\(f_i\)最终取值唯一,可当作分组背包处理。将大小为\(i\)的\(t\)......
  • 洛谷 P11012 颜料
    洛谷P11012颜料题意给出长度为\(n\)的序列\(a\)。定义一段区间\([l,r]\)的绚丽程度\(X_{l,r}\)为\(\sum_{i=1}^{W}\sum_{j=i+1}^W\min(c_i,c_j)\),其中\(W\)是值域,\(c_i\)表示\(a\)序列\([l,r]\)中\(i\)出现的次数,求绚丽程度至少为\(k\)的区间长度最小值。......
  • 洛谷 P11011 点的覆盖
    洛谷P11011点的覆盖题意给定一个四边平行于坐标轴的矩形\(A\),给定\(n\)个在矩形\(A\)内部(可能在边缘上)的点。求有多少个\(A\)的子矩形覆盖了所有\(n\)个点(允许在边缘上)。所有坐标都是整数。思路求出:\(X_1=\max_{i=1}^nx_i\),\(X_2=\min_{i=1}^nx_i\),\(Y_1=\max_......
  • CCF-CSP 2024 --重塑矩阵1,2c语言题解
     创作想法是因为像我当初大一时候想参加一些比赛但是奈何只学了c和c相关数据结构,但是对于许多竞赛的题目的题解往往都是c++或者其他面向对象的编程语言,让我们难以在c语言基础上入手这些比较复杂的题目。 创造的目的是为了帮助各位同时提高我对c语言编程的理解和锻炼个人......
  • CSP-J 2020 初赛试题解析(第一部分:单项选择题(5-10))
    ......
  • 【秋招笔试】8.30饿了么秋招(算法岗)-三语言题解
    ......
  • Leetcode 第 408 场周赛题解
    Leetcode第408场周赛题解Leetcode第408场周赛题解题目1:3232.判断是否可以赢得数字游戏思路代码复杂度分析题目2:3233.统计不是特殊数字的数字数量思路代码复杂度分析题目3:3234.统计1显著的字符串的数量思路代码复杂度分析题目4:3235.判断矩形的两个角落是否......