地址  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. 奇偶游戏 并查集的更多相关文章

  1. AcWing 239.奇偶游戏 (带权并查集/种类并查集)

    题意:你和朋友玩游戏,有个一\(01\)序列,你每次给出一个区间,朋友会回答这个区间中的\(1\)的个数是奇数还是偶数,但是你亲爱的朋友可能在撒谎,问在哪个询问你能确定你的朋友在撒谎,输出回合数. 题 ...

  2. acwing 1250. 格子游戏 并查集

    地址 https://www.acwing.com/problem/content/1252/ Alice和Bob玩了一个古老的游戏:首先画一个 n×nn×n 的点阵(下图 n=3n=3 ). 接着, ...

  3. AcWing 239. 奇偶游戏

    小A和小B在玩一个游戏. 首先,小A写了一个由0和1组成的序列S,长度为N. 然后,小B向小A提出了M个问题. 在每个问题中,小B指定两个数 l 和 r,小A回答 S[l~r] 中有奇数个1还是偶数个 ...

  4. AcWing:239. 奇偶游戏(前缀和 + 离散化 + 带权并查集 + 异或性质 or 扩展域并查集 + 离散化)

    小A和小B在玩一个游戏. 首先,小A写了一个由0和1组成的序列S,长度为N. 然后,小B向小A提出了M个问题. 在每个问题中,小B指定两个数 l 和 r,小A回答 S[l~r] 中有奇数个1还是偶数个 ...

  5. BZOJ 1854: [Scoi2010]游戏 并查集

    1854: [Scoi2010]游戏 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 2672  Solved: 958[Submit][Status][ ...

  6. 1854: [Scoi2010]游戏[并查集]

    1854: [Scoi2010]游戏 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 4938  Solved: 1948[Submit][Status] ...

  7. 洛谷 P1640 SCOI2010 连续攻击游戏 并查集

    题目描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备 ...

  8. bzoj 1854: [Scoi2010]游戏 (并查集||二分图最大匹配)

    链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1854 写法1: 二分图最大匹配 思路:  将武器的属性对武器编号建边,因为只有10000种 ...

  9. 【bzoj1854】[Scoi2010]游戏 - 并查集

    lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备最多只能使 ...

随机推荐

  1. HDU-1024_Max Sum Plus Plus

    Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) P ...

  2. phpexcel使用说明3

    下面是总结的几个使用方法 include 'PHPExcel.php'; include 'PHPExcel/Writer/Excel2007.php'; //或者include 'PHPExcel/ ...

  3. Python基础:08列表解析与生成器表达式

    一:列表解析 列表解析(List comprehensions)来自函数式编程语言Haskell .它可以用来动态地创建列表.它在 Python 2.0 中被加入. 列表解析的语法:     [exp ...

  4. laravel 的路由中间件

    简介# Laravel 中间件提供了一种方便的机制来过滤进入应用的HTTP请求.例如,Laravel 内置了一个中间件来验证用户的身份认证 , 如果没有通过身份认证,中间件会将用户重定向到登陆界面,但 ...

  5. @bzoj - 4378@ [POI2015] Pustynia

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个长度为 n 的正整数序列 a,每个数都在 1 到 10^ ...

  6. HZOJ 分组

    打了好多个代码. 对于测试点1,11:手动模拟. void QJ1_11() { ) { int tk; ]+a[]))tk=; ; if(tk<=k) { puts("); puts ...

  7. Android Joda-time工具类

    Joda-Time提供了一组Java类包用于处理包括ISO8601标准在内的date和time.可以利用它把JDK Date和Calendar类完全替换掉,而且仍然能够提供很好的集成.   Joda- ...

  8. mysql数据库之单表查询

    单标查询 单表查询语句 关键字执行的优先级 简单查询 where约束 group by 聚合函数 HAVING过滤 order by 查询排序 LIMIT限制查询的记录数 使用正则表达式查询 单表查询 ...

  9. H3C 分页显示

  10. 学习框架/对象onbeforeunload事件

    1.有没有发现在一些表单提交页面,当我们点击页面某个链接要离开表单提交页面时会弹出一个提示信息,如下: 那么,这是提示是怎么产生的呢?代码如下: window.onbeforeunload=funct ...