[CEOI1999]Parity Game 题解
P5937 [CEOI1999]Parity Game
洛谷P5937 P5937 [CEOI1999]Parity Game
前言:
个人感觉这道题初看想不到并查集啊!(说实话我题都没读懂,第二遍才读懂)
好了,转入正题,这道题我们可以用两种方法A掉:种类并查集&带权并查集
题目简述:
给定01序列的长度n,询问和答案的个数m
对于每行的询问和回答先给出两个整数,表示询问区间(闭区间)
再给出一个字符串回答:“odd”表示区间有奇数个1,“even”表示区间有偶数个1
如果存在一个01序列满足第1个到第x个的回答,不满足第x+1个回答,则输出x(如果m个回答都满足,那肯定就输出m)
数据范围:
对于100%的数据,1≤N≤10^9,1≤M≤5×10^3
因为N有点大,所以我们需要使用到离散化! 来将大数据映射到小范围的小数据
引入:
其实本题和程序自动分析这道题很像:都是给定若干个变量和关系,判断这些关系的可满足性问题
不过我们这道题的传递关系不止一种(涉及到了奇偶性):
若x1与x2的奇偶性相同,x2与x3的奇偶性相同,那么x1与x3的奇偶性相同
若x1与x2的奇偶性相同,x2与x3的奇偶性不同,那么x1与x3的奇偶性不同
若x1与x2的奇偶性不同,x2与x3的奇偶性不同,那么x1与x3的奇偶性不同
种类并查集:
(因为我认为这道题种类并查集比较好想也比较好理解,所以先讲种类并查集的做法ovo,下面通过问答的形式给出思路)
- 为什么想到种类并查集?
本题需要记录与自己相同的和不同的,那么我们可以将相同的理解为“朋友”,将不同的理解为“敌人”
而题目中的奇偶性又具有传递性(见上“引入部分”),所以我们还需要维护这种传递性——于是我们想到了种类并查集
- 怎么维护传递性&怎么判断回答是否正确?
- 每遇到一个回答,我们先判断当前两个区间端点的奇偶性:
①对于“even”回答,若左端点在右端点“敌人”的集合中或右端点在左端点“敌人”的集合中,则回答错误
②对于“odd”回答,若左端点在右端点“朋友”的集合中或右端点在左端点“朋友”的集合中,则回答错误
- 如果回答是正确的,那我们就进行合并操作:
①对于“even”,我们将左端点和右端点的“朋友”、“敌人”集合分别合并
②对于“odd”,我们将左端点的“朋友”与右端点的“敌人”合并,将左端点的“敌人”与右端点的“朋友”合并
- 怎么离散化?
可见浅谈离散化这篇博客qvq
- 下面给出种类并查集做法的完整代码:
#include <bits/stdc++.h>
using namespace std;
int n,m,tot,res,b[100010],fa[100010];
struct node {
int u,v;
string op;
} a[100010];
inline int find(int x) {
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
int main() {
scanf("%d%d",&n,&m);
for(register int i=1;i<=m;i++) {
scanf("%d%d",&a[i].u,&a[i].v);
cin>>a[i].op;
b[++tot]=a[i].u;
b[++tot]=a[i].v;
}
sort(b+1,b+1+tot);
res=unique(b+1,b+1+tot)-(b+1);
for(register int i=1;i<=m;i++) { //STL实现离散化的三部曲
a[i].u=lower_bound(b+1,b+1+res,a[i].u-1)-b;
a[i].v=lower_bound(b+1,b+1+res,a[i].v)-b;
}
for(register int i=1;i<=2*res;i++) fa[i]=i;
for(register int i=1;i<=m;i++) {
if(a[i].op=="even") { //如果回答是偶数个
if(find(a[i].u)==find(a[i].v+res)||find(a[i].u+res)==find(a[i].v)) { //判断奇偶性
printf("%d",i-1); //注意是i-1而不是i
return 0;
}
fa[find(a[i].u)]=find(a[i].v);
fa[find(a[i].u+res)]=find(a[i].v+res);
}
else {
if(find(a[i].u)==find(a[i].v)||find(a[i].u+res)==find(a[i].v+res)) {
printf("%d",i-1);
return 0;
}
fa[find(a[i].u)]=find(a[i].v+res);
fa[find(a[i].u+res)]=find(a[i].v);
}
}
printf("%d",m);
return 0;
}
带权并查集:
- 怎么想到带权并查集?
我们不妨将区间转换为一棵树,然后用0/1来表示边权,如下草图:
我们可以发现,任意区间都可在在树上表示并求得区间的奇偶性(0/1连成字符串就好)
- 怎么转换为维护带权并查集?
我们将输入中的回答转换为0或1存储:“even”标记为0,“odd”标记为1
我们用dis[x]来记录x与fa[x]的奇偶性关系:为0就相同,反之不同
在路径压缩时,对x到根节点路径上的所有边权做异或(xor)运算,就可以得到x与root的奇偶性关系(都是0/1,所以想到异或)
如上图:dis[x]=1 xor 0 xor 1=0,dis[y]=0 xor 1 xor 1=0
- 对于每个问题,先检查左右端点是否在同一个集合内(奇偶性是否已知):
①在的话就计算dis[l] xor dis[r](即两端点的奇偶性关系),若与回答相矛盾(dis[l] xor dis[r]≠ans),那么回答错误
②不在的话就进行合并操作。此时设两个集合的树根为xl、xr,令xl作为xr的孩子,那就要求出dis[xl]=dis[l] xor dis[r] xor ans
- 下面给出带权并查集做法的完整代码:
#include <bits/stdc++.h>
using namespace std;
string s;
int n,m,tot,res;
int b[100010],fa[100010],dis[100010];
struct node {
int u,v,op;
} a[100010];
inline int find(int x) {
if(fa[x]==x) return x;
int root=find(fa[x]);
dis[x]^=dis[fa[x]]; //路径压缩求出x与树根的奇偶性关系
return fa[x]=root;
}
int main() {
scanf("%d%d",&n,&m);
for(register int i=1;i<=m;i++) {
scanf("%d%d",&a[i].u,&a[i].v);
cin>>s;
if(s=="even") a[i].op=0; //转换回答
else a[i].op=1;
b[++tot]=a[i].u;
b[++tot]=a[i].v;
}
sort(b+1,b+1+tot);
res=unique(b+1,b+1+tot)-(b+1);
for(register int i=1;i<=2*res;i++) fa[i]=i;
for(register int i=1;i<=m;i++) {
int x=lower_bound(b+1,b+1+res,a[i].u-1)-b; //直接判断一个取一个,就不用单独处理
int y=lower_bound(b+1,b+1+res,a[i].v)-b;
int xx=find(x),yy=find(y);
if(xx==yy) { //在一个集合中
if((dis[x]^dis[y])!=a[i].op) { //判断回答是否正确
printf("%d",i-1);
return 0;
}
}
else {
fa[xx]=yy;
dis[xx]=dis[x]^dis[y]^a[i].op; //求左端点树根成为右端点树根孩子后的边权
}
}
printf("%d",m);
return 0;
}
然后,感谢一下我的同桌给我的指导
最后,有什么问题欢迎各位dalao们指出来qwq
[CEOI1999]Parity Game 题解的更多相关文章
- 题解 P5937 【[CEOI1999]Parity Game】
这道题有两种做法,一种是 扩展域(种类并查集),一种是 边带权(带权并查集).种类并查集貌似应该都比带权并查集简单,所以先讲种类并查集的做法,再讲带权并查集 种类并查集 若 sum[ l ~ r ] ...
- 算法与数据结构基础 - 排序(Sort)
排序基础 排序方法分两大类,一类是比较排序,快速排序(Quick Sort).归并排序(Merge Sort).插入排序(Insertion Sort).选择排序(Selection Sort).希尔 ...
- 算法与数据结构基础 - 数组(Array)
数组基础 数组是最基础的数据结构,特点是O(1)时间读取任意下标元素,经常应用于排序(Sort).双指针(Two Pointers).二分查找(Binary Search).动态规划(DP)等算法.顺 ...
- CF1272E. Nearest Opposite Parity 题解 广度优先搜索
题目链接:http://codeforces.com/contest/1272/problem/E 题目大意: 有一个长度为n的数组 \(a\) ,数组坐标从 \(1\) 到 \(n\) . 假设你现 ...
- CF1110A Parity 题解
Content 求下面式子的奇偶性,其中 \(a_i,k,b\) 会在输入中给定. \[\sum\limits_{i=1}^k a_i\cdot b^{k-i} \] 数据范围:\(2\leqslan ...
- Codeforces 549C. The Game Of Parity[博弈论]
C. The Game Of Parity time limit per test 1 second memory limit per test 256 megabytes input standar ...
- Codeforces Round #180 (Div. 2) C. Parity Game 数学
C. Parity Game 题目连接: http://www.codeforces.com/contest/298/problem/C Description You are fishing wit ...
- poj1733 Parity Game(扩展域并查集)
描述 Now and then you play the following game with your friend. Your friend writes down a sequence con ...
- POJ1733 Parity game 【扩展域并查集】*
POJ1733 Parity game Description Now and then you play the following game with your friend. Your frie ...
随机推荐
- (Java实现) 洛谷 P1605 迷宫
题目背景 迷宫 [问题描述] 给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过.给定起点坐标和 终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案.在迷宫 中移动有上下 ...
- Java实现 LeetCode 539 最小时间差(单位转换)
539. 最小时间差 给定一个 24 小时制(小时:分钟)的时间列表,找出列表中任意两个时间的最小时间差并已分钟数表示. 示例 1: 输入: ["23:59","00:0 ...
- Java实现 洛谷 P1103 书本整理
题目描述 Frank是一个非常喜爱整洁的人.他有一大堆书和一个书架,想要把书放在书架上.书架可以放下所有的书,所以Frank首先将书按高度顺序排列在书架上.但是Frank发现,由于很多书的宽度不同,所 ...
- CICD | Jenkins & Gitlab集成:WebHook触发构建
在上一篇博客中,我们学习了Jenkins的搭建和插件+流水线的基本使用方法,Jenkins极大地提升了部署效率. 最近想学习一下如何集成GitLab webhook,实现进一步解放双手,目标: 推送( ...
- 温故知新-java的I/O模型-BIO&NIO&AIO
文章目录 摘要 传统的BIO编程 伪异步I/O编程 NIO编程 AIO编程 几种IO模型的对比 netty 参考 你的鼓励也是我创作的动力 Posted by 微博@Yangsc_o 原创文章,版权声 ...
- Servlet中的请求转发
请求转发时,传递到下一个servlet的request和response可能内存地址不同,但是里面包含的内容是相同的 // servlet1 RequestDispatcher dispatcher ...
- 实验二 Linux系统简单文件操作命令
项目 内容 这个作业属于哪个课程 班级课程的主页链接 这个作业的要求在哪里 作业要求链接接地址 学号-姓名 17041428-朱槐健 作业学习目标 1.学习在Linux系统终端下进行命令行操作 2.掌 ...
- Jquery封装: 地区选择联动插件
请点击下载百度云链接: 链接: https://pan.baidu.com/s/1plVmdJT2O4fLJokyJDQA2g 密码: aqt2
- RabbitMQ系列之【CentOS6.5安装RabbitMQ】
环境准备 操作系统:CentOS 6.5 Final RabbitMQ: 3.1.5 Python: 2.7.11 ErLang: R16B02 安装预环境(少什么安装什么) yum -y insta ...
- [原创][开源] SunnyUI.Net 开发日志:UIBarChart 坐标轴刻度取值算法
_ 在开发UIBarChart的过程中,需要绘制Y轴的刻度,数据作图时,纵横坐标轴刻度范围及刻度值的取法,很大程度上取决于数据的分布.对某一组数据,我们很容易就能知道如何选取这些值才能使图画得漂亮.但 ...