acwing 239. 奇偶游戏 并查集
地址 https://www.acwing.com/problem/content/241/
小A和小B在玩一个游戏。
首先,小A写了一个由0和1组成的序列S,长度为N。
然后,小B向小A提出了M个问题。
在每个问题中,小B指定两个数 l 和 r,小A回答 S[l~r] 中有奇数个1还是偶数个1。
机智的小B发现小A有可能在撒谎。
例如,小A曾经回答过 S[1~3] 中有奇数个1, S[4~6] 中有偶数个1,现在又回答 S[1~6] 中有偶数个1,显然这是自相矛盾的。
请你帮助小B检查这M个答案,并指出在至少多少个回答之后可以确定小A一定在撒谎。
即求出一个最小的k,使得01序列S满足第1~k个回答,但不满足第1~k+1个回答。
输入格式
第一行包含一个整数N,表示01序列长度。
第二行包含一个整数M,表示问题数量。
接下来M行,每行包含一组问答:两个整数l和r,以及回答“even”或“odd”,用以描述S[l~r] 中有奇数个1还是偶数个1。
输出格式
输出一个整数k,表示01序列满足第1~k个回答,但不满足第1~k+1个回答,如果01序列满足所有回答,则输出问题总数量。
数据范围
N≤10^9,M≤
输入样例: even
odd
even
even
odd
输出样例:
解答1:
带权并查集
本题目有两个难点
1 数据范围过大 有 10^9
2 询问的内容如何转化到并查集
问题1 的解决办法是 使用离散化 将不同的数据映射到1 2 3 4。。。,由于只有10000次 询问,每次询问提供两个数据 所以只要提供10000*2的数据范围即可
问题2 的解决办法是 前缀和 如果提供 l和r的范围内1有奇数个还是偶数个 也就是计算 前缀和 sum[r] - sum[l-1]
另由于有偶数减偶数 奇数减奇数 都是偶数 只有两者不同类型分别是奇数偶数中的一种 才会出现最后的差是奇数
那么并查集其实也就是前缀和中每个元素的奇偶性
增加带权数组 所有的前缀和元素都会合并到一个祖先中,d[x]带权数组会记录x元素是否与根是同样的奇偶性
当得到新的询问时候 如果两个元素已经合并在同一个祖先下,那么就可以根据他们与祖先的异同得到他们的异同,再来判断他们与输入的异同是否一致 如果不一致就是发生矛盾,返回即可
代码如下
#include <iostream>
#include <string>
#include <unordered_map> using namespace std; const int MAX_M = ; int N, M;
int n, m; int fa[MAX_M];
int d[MAX_M]; int idx = ; unordered_map<int, int> S; //离散化
int get(int x) {
if (S.count(x) == ) S[x] = ++idx;
return S[x];
} void init()
{
for (int i = ; i < MAX_M; i++) {
fa[i] = i;
}
} int find(int x) {
if (fa[x] != x) {
int root = find(fa[x]);
d[x] += d[fa[x]]%;
fa[x] = root;
} return fa[x];
} int main()
{ cin >> n >> m;
int res = m;
init();
for (int i = ; i <= m; i++) {
int a, b; string s;
cin >> a >> b >> s;
a = get(a - ); b = get(b);
int pa = find(a), pb = find(b); if (pa == pb) {
//查看两者是否符合之前的信息
if (s == "even")
{
//两者奇偶性相同
if( (d[a] + d[b]) % != ){
//有矛盾
res = i - ;
break;
}
}
else if (s == "odd") {
//两者奇偶性不同
if ((d[a] + d[b]) % != ) {
//有矛盾
res = i - ;
break;
}
}
else {
cout << s << endl;
cout << "error" << endl;
break;
}
}
else {
//pa != pb
//合并
fa[pa] = pb;
int add = ;
if (s == "odd") add = ;
d[pa] = (d[a] + d[b] + add)%;
} }
cout << res << endl; return ;
}
带权并查集
解法2 并查集扩展域
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map> using namespace std; const int MAX_N = *;
const int Base = MAX_N / ; unordered_map<int, int> S;
int n, m; int p[MAX_N]; int idx = ;
//离散化
int get(int x) {
if (S.count(x) == ) S[x] = ++idx;
return S[x];
} int find(int x)
{
if (x != p[x]) p[x] = find(p[x]); return p[x];
} int main()
{
cin >> n >> m; int res = m;
for (int i = ; i < MAX_N; i++) p[i] = i; for (int i = ; i <= m; i++) {
int a, b; string s;
cin >> a >> b >> s;
a = get(a - ); b = get(b); if (s == "even") {
//相同
if (find(a + Base) == find(b)) {
res = i - ;
break;
}
p[find(a)] = find(b);
p[find(a + Base)] = p[find(b + Base)];
}
else {
if (find(a) == find(b)) {
res = i - ;
break;
}
p[find(a+Base)] = find(b);
p[find(a )] = p[find(b + Base)]; } }
cout << res << endl; return ;
}
扩展域
acwing 239. 奇偶游戏 并查集的更多相关文章
- AcWing 239.奇偶游戏 (带权并查集/种类并查集)
题意:你和朋友玩游戏,有个一\(01\)序列,你每次给出一个区间,朋友会回答这个区间中的\(1\)的个数是奇数还是偶数,但是你亲爱的朋友可能在撒谎,问在哪个询问你能确定你的朋友在撒谎,输出回合数. 题 ...
- acwing 1250. 格子游戏 并查集
地址 https://www.acwing.com/problem/content/1252/ Alice和Bob玩了一个古老的游戏:首先画一个 n×nn×n 的点阵(下图 n=3n=3 ). 接着, ...
- AcWing 239. 奇偶游戏
小A和小B在玩一个游戏. 首先,小A写了一个由0和1组成的序列S,长度为N. 然后,小B向小A提出了M个问题. 在每个问题中,小B指定两个数 l 和 r,小A回答 S[l~r] 中有奇数个1还是偶数个 ...
- AcWing:239. 奇偶游戏(前缀和 + 离散化 + 带权并查集 + 异或性质 or 扩展域并查集 + 离散化)
小A和小B在玩一个游戏. 首先,小A写了一个由0和1组成的序列S,长度为N. 然后,小B向小A提出了M个问题. 在每个问题中,小B指定两个数 l 和 r,小A回答 S[l~r] 中有奇数个1还是偶数个 ...
- BZOJ 1854: [Scoi2010]游戏 并查集
1854: [Scoi2010]游戏 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 2672 Solved: 958[Submit][Status][ ...
- 1854: [Scoi2010]游戏[并查集]
1854: [Scoi2010]游戏 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 4938 Solved: 1948[Submit][Status] ...
- 洛谷 P1640 SCOI2010 连续攻击游戏 并查集
题目描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备 ...
- bzoj 1854: [Scoi2010]游戏 (并查集||二分图最大匹配)
链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1854 写法1: 二分图最大匹配 思路: 将武器的属性对武器编号建边,因为只有10000种 ...
- 【bzoj1854】[Scoi2010]游戏 - 并查集
lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备最多只能使 ...
随机推荐
- VirtualBox使用随笔
1.virtualbox配置Android手机USB热点 host:Windows10;guest:windows XP/10 右击我的电脑 - 管理 - 设备管理器 - 网卡适配器,若手机正确vb连 ...
- @atcoder - AGC034D@ Manhattan Max Matching
目录 @description@ @solution@ @accepted code@ @details@ @description@ 考虑一个二维平面,执行共 2*N 次操作: 前 N 次,第 i ...
- TensorFlow 池化层
在 TensorFlow 中使用池化层 在下面的练习中,你需要设定池化层的大小,strides,以及相应的 padding.你可以参考 tf.nn.max_pool().Padding 与卷积 pad ...
- 仿IOS效果-带弹簧动画的ListView
背景介绍 最近项目打算做一个界面,类似于dayone首页的界面效果,dayone 是一款付费应用,目前只有IOS端.作为一个资深懒惰的程序员,奉行的宗旨是绝对不重复造一个轮子.于是乎,去网上找一大堆开 ...
- 谷歌BERT预训练源码解析(二):模型构建
目录前言源码解析模型配置参数BertModelword embeddingembedding_postprocessorTransformerself_attention模型应用前言BERT的模型主要 ...
- @bzoj - 4379@ [POI2015] Modernizacja autostrady
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一棵无根树,边权都是1,请去掉一条边并加上一条新边,定义直径 ...
- 在web.xml中配置SpringMVC
代码如下 <servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.spr ...
- H3C 路由器的作用
- [C#] 如何把void*转换为byte[]
一般来说,C#库的对外接口应该提供byte[]这样比较容易用的接口,而不应该提供裸的void* 但是有些库确实是这么封装的.那么就有一个如何转换的问题.MSDN推荐的转换方式是使用UnmanagedM ...
- 使用openssl 工具进行双向认证测试
1,双向认证测试(需要根证书,客户证书,服务器证书以及各自的私钥)(验证通信双方的身份) openssl s_server -accept -key certs/server.key -cert ce ...