Parity Game——种类并查集、权值并查集、离散化

题目描述

思路

怎么得到这个序列中每一段的关系?

  • 我们可以把这个只包含0和1的序列看作一个数组,0表示当前位置为0,1表示当前位置为1,利用前缀和的性质可以知道某一段中所包含的1的数量
  • sum1 = a[r] - a[l-1]
  1. 如果sum1为偶数,那么a[r] 和 a[l-1]的奇偶性相同
  2. 如果sum1为奇数,那么a[r] 和 a[l-1]的奇偶性不同
  • 找到它们之间的关系,我们就可以使用并查集来存储他们

为什么要离散化?

  • 序列的长度小于等于1e9,然而序列中下标出现的次数最多为1e4,所以使用离散化

种类并查集

  • 序列中某一段有两种关系,奇数个1、偶数个1
  • 我们定义两个扩展域,1~n表示偶数,n + 1 ~ 2 * n表示奇数
  • 每次知道一个关系之后,将偶数区域和奇数区域都进行处理,像枚举一样,不漏掉每一种情况
  • 并查集中存储的是区域与区域之间的关系,如果有一个关系成立,那么这个集合中其它的关系都成立

代码实现

#include <iostream>
#include <algorithm>
#include <vector>using namespace std;const int N = 1e4 + 10;int fa[2 * N];		// 两个扩展域:1~N表示偶数关系,N+1~2N表示奇数关系
int n, m;
vector<int> ans;	// 离散化数组struct node	// 结构体,存储每一段区间的左右端点
{int x, y;string op;
}a[N];int get(int u)	// 二分查找,将原数据离散化成下标
{int l = 0, r = ans.size();while(l + 1 != r){int mid = l + r >> 1;if(ans[mid] < u) l = mid;else r = mid;}return r;
}int find(int u)		// 返回当前元素的祖宗元素,在哪个集合中
{if(fa[u] != u) fa[u] = find(fa[u]);return fa[u];
}void merge(int x, int y)	// 将x合并到y所在的集合中
{fa[find(x)] = find(y);
}int main()
{cin >> n >> m;for(int i = 1; i <= m; i++){cin >> a[i].x >> a[i].y >> a[i].op;	a[i].x--;	// 因为利用了前缀和的性质,所以要将左端点-1,满足sum = a[r] - a[l-1]ans.push_back(a[i].x);ans.push_back(a[i].y);}sort(ans.begin(), ans.end());	// 将数据进行排序ans.erase(unique(ans.begin(), ans.end()), ans.end());	// 进行去重ans.insert(ans.begin(), 0);	// 将离散化之后的下标从1开始for(int i = 1;i <= m; i++)	// 找到每个区间左右端点离散化之后的数据,使用新数据{a[i].x = get(a[i].x);a[i].y = get(a[i].y);}for(int i = 0;i < 2 * N; i++) fa[i] = i;	// 初始化集合,每一个元素在不同的集合中n = ans.size();	// 每个扩展域的范围for(int i = 1; i <= m; i++)	// 开始遍历每一个回答,判断左右端点集合中的关系{int x = a[i].x, y = a[i].y;string op = a[i].op;if(op == "even")	// 有偶数个1{// 只需要判断一种情况就可,因为他们的关系是对称的if(find(x) == find(y + n))	// x为偶数的集合中,存在y为奇数的关系,矛盾{cout << i - 1 << endl;return 0;}// x与y的奇偶性相同merge(x, y); 	// 将x为偶数,y为偶数放在一个集合中merge(x + n, y + n);	// 将x为奇数,y为奇数放在一个集合中}else	// 有奇数个1,那么x和y的奇偶性不同{if(find(x) == find(y))	// x为偶数的集合中,存在y为偶数的关系,矛盾{cout << i - 1 << endl;return 0;}merge(x, y + n);	// 将x为偶数,y为奇数放在一个集合中merge(x + n, y);	// 将x为奇数,y为偶数放在一个集合中}}cout << m << endl;return 0;
}

权值并查集

  • 每一个区间的奇偶性有两种情况,奇数或者偶数
  • 我们可以维护集合中每个区间的关系,这个关系可以用集合中的子区间到祖宗区间的距离来表示,因为有两种情况,所以当距离d[i] % 2 == 0时,当前区间的奇偶性和祖宗元素的奇偶性相同,d[i] % 2 ==1时,当前区间的奇偶性和祖宗元素的奇偶性不同
  • 每一个集合中的区间相对于祖宗区间的奇偶性是已知的,所以集合中所有区间的奇偶性关系都是已知的

代码实现

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;const int N = 1e5 + 10;int fa[N];	// 初始化每一个集合都是独立的
int d[N];	// 集合中子区间到祖宗区间的距离,可以判断奇偶关系
vector<int> ans;	// 离散化数组
int n, m;struct node	// 存储每一个回答
{int x, y;string op;
}a[N];int get(int u)	// 二分查找进行离散化
{int l = 0, r = ans.size();while(l + 1 != r){int mid = l + r >> 1;if(ans[mid] < u) l = mid;else r = mid;}return r;
}int find(int u)	// 找到当前区间的祖宗区间,并进行路径压缩和更新到祖宗区间的距离
{if(fa[u] != u){int t = find(fa[u]);d[u] += d[fa[u]];fa[u] = t;}return fa[u];
}int main()
{cin >> n >> m;for(int i = 1;i <= m; i++){cin >> a[i].x >> a[i].y >> a[i].op;a[i].x--;ans.push_back(a[i].x);ans.push_back(a[i].y);}sort(ans.begin(), ans.end());ans.erase(unique(ans.begin(), ans.end()), ans.end());ans.insert(ans.begin(), 0);for(int i = 1; i <= m; i++) {a[i].x = get(a[i].x);a[i].y = get(a[i].y);}for(int i = 1; i <= ans.size(); i++) fa[i] = i;for(int i = 1;i <= m; i++){int fx = find(a[i].x), fy = find(a[i].y);string op = a[i].op;if(op == "even"){if(fx != fy){d[fx] = d[a[i].x] ^ d[a[i].y];fa[fx] = fy;}else {if((d[a[i].x] + d[a[i].y]) % 2 != 0){cout << i - 1 << endl;return 0;}}}else{if(fx != fy){d[fx] = d[a[i].x] ^ d[a[i].y] ^ 1;fa[fx] = fy;}else{if((d[a[i].x] + d[a[i].y]) % 2 == 0){cout << i - 1 << endl;return 0;}}}}cout << m << endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/195239.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式-行为型模式-模板方法模式

一、什么是模板模式 模板方法模式&#xff08;Template Method Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一个算法骨架&#xff0c;允许子类在不改变算法整体结构的情况下重新定义算法的某些步骤。 主要组成部分&#xff1a; 1、模板方法&#xff08;Templ…

HR应用在线人才测评,给企业招聘带来的好处

一、什么是人才测评&#xff1f; 人才测评是指运用一系列的科学方法&#xff0c;对人的基本素质&#xff0c;专业能力&#xff0c;心理健康&#xff0c;性格进行选拔&#xff0c;评价及发展人才的一种科学方法。近十多年&#xff0c;它被广泛运用于国有大型企业的人才招聘和人…

MISRA 2012学习笔记(5)-Rules 8.10

文章目录 Rules8.10 基本类型模型(The essential type model)8.10.1 原理8.10.2 基本类型(Essential type)Rule 10.1 操作数不得具有不适当的基本类型Rule 10.2 在加减法运算中&#xff0c;不得不当使用本质为字符类型的表达式Rule 10.3 表达式的值不得赋值给具有较窄基本类型或…

论文阅读——DiffusionDet

在目标检测上使用扩散模型 前向过程&#xff1a;真实框-->随机框 后向过程&#xff1a;随机框-->真实框 前向过程&#xff1a; 一般一张图片真实框的数目不同&#xff0c;填补到同一的N个框&#xff0c;填补方法可以是重复真实框&#xff0c;填补和图片大小一样的框&a…

鸿蒙:使用Stack、ContentTable、Flex等组件和布局实现一个显示界面

效果展示 一.概述 跟随官网继续HarmonyOS学习 本篇博文实现一个食物详情页的开发Demo 通过这个开发过程学习如何使用容器组件Stack、Flex和基本组件Image、Text&#xff0c;构建用户自定义组件&#xff0c;完成图文并茂的食物介绍 二.构建Stack布局 1.食物名称 创建Stack…

运行ps显示msvcp140.dll丢失怎么恢复?msvcp140.dll快速解决的4个不同方法

msvcp140.dll无法继续执行代码的主要原因有以下几点 系统缺失&#xff1a;msvcp140.dll是Visual Studio 2015编译的程序默认的库文件&#xff0c;如果系统中没有这个库文件&#xff0c;那么在运行相关程序时就会出现找不到msvcp140.dll的错误提示。 文件损坏&#xff1a;如果…

左支座零件的机械加工工艺规程及工艺装备设计【计算机辅助设计与制造CAD】

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;左支座 获取完整CAD工程源文件论文报告说明书等 一、论文目录 二、论文部分内容 设计任务 1.完成左支座零件—毛坯合图及左支座零件图 2.完成左支座零件工艺规程设计 3.完成左支座零件加工工艺卡 4.机床专用夹具装备总图 …

基于SSM的“鲜花”电子商务平台设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

YOLO免费数据集网站收集

目录 Roboflow Universe: Open Source Computer Vision Community Find Open Datasets and Machine Learning Projects | Kaggle ​编辑 【火焰和烟雾图像数据集】-计算机视觉数据集-极市开发者平台 (cvmart.net) 开放数据集- 飞桨AI Studio星河社区 - 人工智能学习与实训社…

AVL树和红黑树

AVL树和红黑树 一、AVL树1. 概念2. 原理AVL树节点的定义插入不违反AVL树性质违反AVL树性质左单旋右单旋左右双旋右左双旋总结 删除 3. 验证代码4. AVL树完整实现代码 二、红黑树1. 概念2. 性质3. 原理红黑树节点的定义默认约定插入情况一 &#xff08;u存在且为红&#xff09;情…

【机器学习13】生成对抗网络

1 GANs的基本思想和训练过程 生成器用于合成“假”样本&#xff0c; 判别器用于判断输入的样本是真实的还是合成的。 生成器从先验分布中采得随机信号&#xff0c;经过神经网络的变换&#xff0c; 得到模拟样本&#xff1b; 判别器既接收来自生成器的模拟样本&#xff0c; 也接…

SPASS-曲线估计

基本概念 曲线估计&#xff08;曲线拟合、曲线回归&#xff09;则是研究两变量间非线性关系的一种方法&#xff0c;选定一种用方程表达的曲线&#xff0c;使得实际数据与理论数据之间的差异尽可能地小。如果曲线选择得好&#xff0c;那么可以揭示因变量与自变量的内在关系&…